uniapp 制作一个可复用的segmented-control(tab选项卡)

uniapp 制作一个可复用的segmented-control(tab选项卡)

开局一张图,内容全靠编

1.开局一张图(先上效果图)

2.内容全靠编

 开始编写复用组件:

 segmented-control.vue

复制代码

<template>
  <view id="segmented" class="segmented" :style="{top:stickyTopData+'px'}">
    <view class="line" :style="{transform:'translateX('+offsetLeft+'px)',width:lineWidth+'px'}"></view>
    <view class="segmented-control">
        <view :id="'sc-'+index" :data-index="index" v-for="(item, index) in values" class="segmented-control-item" :key="index" :class="index === current ? 'active' : ''"
            @click="onClick">
            {{item}}
        </view>
    </view>
  </view>
    
</template>

<script>
export default {
  name: 'segmented-control',
  props: {
    values: { // 要显示的数组
      type: Array,
      default() {
        return [];
      }
    },
    stickyTop:{ // 距离头部多少px将其固定
      type: Number,
      default(){
        return 0;
      }
    },
    current: { // 当前选中第几个
      type: Number,
      default(){
        return 1;
      }
    }
  },
  data() {
    return {
      lineWidth: 0, // 线的宽度
      offsetLeft: 0 // 相对左边的距离
    };
  },
  methods: {
    /**
     * 点击事件
     */
    onClick(e) {
      let index = parseInt(e.mp.target.dataset.index);
      let that = this;
      let id = e.mp.target.id;
      if (that.current !== index) {
        that.$emit('clickItem', index); // 父级组件回调方法
      }
    }
  },
  mounted() {
    let that = this;
    if (that.values) {
      if (that.values && that.values[that.current]) {
        that.lineWidth = 0;
        setTimeout(() => { // 延时获取线的宽度和左边距离
          const query = uni.createSelectorQuery();
          query.select('#sc-' + that.current).boundingClientRect();
          query.exec(res => {
            that.offsetLeft = res[0].left + 16;
            that.lineWidth = res[0].width - 70;
          });
        }, 500);
      }
    }
  },
  computed:{
    stickyTopData:function(){
      return uni.upx2px(this.stickyTop); // 顶部固定显示距离
    }
  },
  watch: {
      current(newValue, oldValue) {
      let that = this;
          setTimeout(() => { // 监听当前选择的item变化,重新计算线的宽和左边的距离
            const query = uni.createSelectorQuery();
            query.select('#sc-' + newValue).boundingClientRect();
            query.exec(res => {
              that.offsetLeft = res[0].left + 16;
              that.lineWidth = res[0].width - 70;
            });
          }, 200);
      }
  },
};
</script>

<style lang="less">
.segmented {
  position: sticky;
}
.segmented-control {
  display: flex;
  background: #ffffff; 
  align-items: center;
  padding: 20upx;
  border-bottom: 1px solid #f6f6f6;
  .segmented-control-item {
    width: 178upx;
    font-size: 32upx;
    color: #999;
  }
  .active {
    color: #333;
  }
}
.line {
  height: 6upx;
  border-radius: 3upx;
  background-color: #E5A600;
  position: absolute;
  top: 80upx;
  left: 0;
  transition: all 0.3s;
}
</style>

复制代码

开始编写父级组件来调用复用组件

list.vue

复制代码

<template>
  <view>
    <segmented-control
      id="tabbar"
      :values="items"
      :stickyTop="108"
      :current="current"
      @clickItem="onClickItem"
    ></segmented-control>
    <view class="list" id="list">{{ current }}</view>
  </view>
</template>

<script>
import segmentedControl from '@/components/segmented-control';

export default {
  components: {
    segmentedControl
  },
  data() {
    return {
      items: ['已完成', '已拒绝', '已取消'],
      current: 0
    };
  },
  methods: {
    /**
     * 点击segmentedControl 事件回调
     */
    onClickItem(index) {
      if (this.current !== index) {
        this.current = index;
      }
    }
  }
};
</script>

<style lang="less">
@import '../../css/list.less';
</style>

复制代码

完事了,上图

 

线的宽度、过渡的时间、样式什么的自己调一调,改一改就行了

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可自定义样式、功能全面的分段控件。项目地址:https://github.com/klongmitre/android-segmented-control-view效果图:如何使用xml中直接创建<org.mitre.ascv.AndroidSegmentedControlView         android:id="@ id/androidSegmentedControlView"         android:layout_width="match_parent"         android:layout_height="wrap_content"         ascv:ascv_defaultSelection="0"         ascv:ascv_unselectedTextColor="@color/test_attr_unselected_text_color"         ascv:ascv_selectedTextColor="@color/test_attr_selected_text_color"         ascv:ascv_selectedColor="@color/test_attr_selected_color"         ascv:ascv_unselectedColor="@color/test_attr_unselected_color"         ascv:ascv_items="@array/three_state_option"/>2. java中添加监听器,监听item的切换ascv = (AndroidSegmentedControlView)this.findViewById(R.id.androidSegmentedControlView); ascv.setIdentifier("ascv01"); //ascv.setItems(new String[]{"Test1aaaaa", "Test2", "Test3"}, new String[]{"1", "2", "3"}); ascv.setOnSelectionChangedListener(new OnSelectionChangedListener(){     @Override     public void newSelection(String identifier, String value) {//当item切换时触发  Toast.makeText(MainActivity.this, "identifier:" identifier "  value:" value, Toast.LENGTH_SHORT).show();     } });参数identifier是当有多个分段控件时,同时使用一个监听器时,用于区别是哪个触发了事件。属性说明属性名类型使用说明ascv_unselectedTextColorreference未选中的item的文字颜色ascv_unselectedColorreference未选中的item的背景颜色,不包括边框ascv_selectedColorreference选中的item背景的颜色以及边框的颜色ascv_selectedTextColorreference选中的item的文字颜色ascv_itemsreference控件item上显示的文字ascv_valuesreference控件item的值,会被传给监听器。未设置时,默认使用ascv_items。ascv_equalWidthboolean当item上的文字,即ascv_items设置的文字,长度不一致时,item的宽度是否还等长。ascv_stretchboolean是否被拉伸。即控件是否填充整个父容器。ascv_defaultSelectioninteger默认哪个item被选中,下标从0开始ascv_identifierstring控件的ID

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值