Android实现动态添加tab并点击移动tab背景

效果图

这里写图片描述

代码

public class TabContainerView extends FrameLayout implements View.OnClickListener{
    private static final String TAG = "TabContainerView";
    private Context mContext;
    private int prePosition,position;
    private onTabSelectedListener mListener;
    private LinearLayout llContainer;
    private ImageView itemBgView;
    private int currentPosition;
    private int offset = 0;
    private int mTotalWidth;
    public TabContainerView(Context context) {
        this(context,null);
    }

    public TabContainerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    public interface onTabSelectedListener{
        void onTabSelected(int position,int totalWidth);
    }

    public void setOnTabSelectedListener(onTabSelectedListener listener){
        mListener = listener;
    }

    public void updateTabItemViews(List<String> tabList,int defaultPosition) {
        if(tabList.size() < 2) {
            setVisibility(GONE);
            return;
        }
        if (tabList != null && tabList.size() > 0) {
            if (defaultPosition > tabList.size()) {
                defaultPosition = tabList.size() - 1;
            }
            if (getChildCount() != 0) {
                removeAllViews();
                //偏移量置为0
                offset = 0;
            }
            llContainer = new LinearLayout(mContext);
            for (int i = 0; i < tabList.size(); i++) {
                TextView tvTabItem = new TextView(mContext);
                tvTabItem.setTextSize(20);
                tvTabItem.setOnClickListener(this);
                tvTabItem.setText(tabList.get(i));
                tvTabItem.setPadding(10, 0, 10, 0);
                tvTabItem.setTag(i);
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                params.weight = 1;
                tvTabItem.setLayoutParams(params);
                llContainer.addView(tvTabItem);
                mTotalWidth += getTabItemWidth(tvTabItem);
            }
            addView(llContainer);
            addView(initTabBgView(defaultPosition));
        }
    }
    @Override
    public void onClick(View v) {
        int distance = 0;
        currentPosition = (int) v.getTag();
        position = currentPosition;
        if(currentPosition == prePosition){
            return;
        }
        if (mListener != null) {
            mListener.onTabSelected(position,mTotalWidth);
        }
        for (int i = 0; i < currentPosition; i++) {
            distance += getTabItemWidth(llContainer.getChildAt(i));
        }
        beginTranslateAndScale(itemBgView,offset,distance,prePosition,currentPosition);
        prePosition = currentPosition;
    }

    /**
     * 设置tab的背景
     * @param position 需要显示背景的tab位置
     * @return
     */
    public ImageView initTabBgView(int position){
        itemBgView = new ImageView(mContext);
        Drawable drawable = getResources().getDrawable(R.drawable.tab_item_bg);
        //设置偏移的位置
        for (int i = 0; i < position; i++) {
            offset += getTabItemWidth(llContainer.getChildAt(i));
        }
        itemBgView.setTranslationX(offset);
        prePosition = position;
        setItemBgWidth(position);
        itemBgView.setImageDrawable(drawable);
        return itemBgView;
    }

    public void setItemBgWidth(int position){
        TextView currentChildView = (TextView) llContainer.getChildAt(position);
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.width = getTabItemWidth(currentChildView);
        params.height = 60;
        itemBgView.setLayoutParams(params);
    }

    /**
     * 获取每个tab的宽度
     * @param tabItem
     * @return
     */
    public int getTabItemWidth(View tabItem){
        int measureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        tabItem.measure(measureSpec,measureSpec);
        return tabItem.getMeasuredWidth();
    }

    public void beginTranslateAndScale(View view,int from,int to,int prePosition,int currentPosition){
        view.setTranslationX(0);
        offset = to;
        Log.d(TAG, "beginTranslateAndScale: "+prePosition+"--"+currentPosition);
        int startWidth = getTabItemWidth(llContainer.getChildAt(prePosition));
        int endWidth = getTabItemWidth(llContainer.getChildAt(currentPosition));
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, "translationX", from, to);
        final ValueAnimator scaleAnimator = ValueAnimator.ofInt(startWidth, endWidth);
        scaleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int animatedValue = (int) scaleAnimator.getAnimatedValue();
                FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                params.width = animatedValue;
                params.height = 60;
                itemBgView.setLayoutParams(params);
            }
        });
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(scaleAnimator,objectAnimator);
        animatorSet.setDuration(1000);
        animatorSet.start();
    }
}

如何使用

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";
    private  List<String> mTitles = Arrays.asList("短信","电话本","消息","语音","聊天","你好","不知道","你好吗","流量充值");
    private TabContainerView tabContainerView;
    private HorizontalScrollView horizontalScrollView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tabContainerView = (TabContainerView) findViewById(R.id.tab_container_view);
        horizontalScrollView = (HorizontalScrollView) findViewById(R.id.horizontal);
       tabContainerView.setOnTabSelectedListener(new TabContainerView.onTabSelectedListener() {
           @Override
           public void onTabSelected(int position, int totalWidth) {
               Log.d(TAG, "onTabSelected: "+totalWidth);
               if(position > 5) {
                   horizontalScrollView.smoothScrollTo(totalWidth,0);
               } else {
                   horizontalScrollView.smoothScrollTo(0,0);
               }
           }
       });
    }

    public void update(View view){
        tabContainerView.updateTabItemViews(mTitles,0);
    }
}

主页面布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.lessonone.MainActivity"
    >
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="update"
        android:text="更新tab"
        />
<com.example.lessonone.TabContainerView
    android:id="@+id/tab_container_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/tab_container_bg"
    android:padding="10dp"
    >
</com.example.lessonone.TabContainerView>
</LinearLayout>

容器背景

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@android:color/holo_blue_light"/>
    <corners android:topRightRadius="8dp"
        android:bottomRightRadius="12dp"/>
</shape>

条目背景

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@android:color/transparent"/>
    <stroke android:color="@android:color/holo_orange_light"
        android:width="2dp"
        />
    <corners android:radius="10dp"/>
</shape>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值