天天看點

自定義TabLayout

自定義TabLayout

最近項目中有用到一個TabLayout,如上圖效果。

先說說需求。

1.Tab的個數是動态變化的。

2.4個Tab占滿一個螢幕,多餘部分往右滑動過來。

3.點選後右側小圖示變化樣式。

思路:

1.布局的話使用LinearLayout布局,放在HorizontalScrollView中。這樣就實作了滾動效果。

2.擷取到螢幕的寬度除以4設定成裡面每個Tab的的寬度。

3.每個Tab使用的也是一個LinearLayout,左側是一個TextView,右側是一個ImageView。

先上代碼:

public class MyTabLayout extends LinearLayout implements View.OnClickListener {
    private final int width;
    private Context context;
    private List<LinearLayout> linearLayoutList = new ArrayList<>();
    private List<ImageView> imageViewList = new ArrayList<>();
    private OnItemClickListener onItemClickListener;

    public OnItemClickListener getOnItemClickListener() {
        return onItemClickListener;
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public MyTabLayout(Context context) {
        this(context, null);
    }

    public MyTabLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        width = wm.getDefaultDisplay().getWidth();
    }

    public void setData(List<String> strings) {
        LinearLayout.LayoutParams layoutParams = new LayoutParams(width / , ViewGroup.LayoutParams.MATCH_PARENT);
        LinearLayout.LayoutParams layoutParams2 = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        for (int i = ; i < strings.size(); i++) {
            LinearLayout linearLayout = new LinearLayout(context);
            linearLayout.setLayoutParams(layoutParams);
            linearLayout.setGravity(Gravity.CENTER);
            linearLayout.setId(i);
            linearLayout.setOnClickListener(this);
            linearLayoutList.add(linearLayout);

            TextView textView = new TextView(context);
            textView.setText(strings.get(i));
            textView.setLayoutParams(layoutParams2);

            ImageView imageView = new ImageView(context);
            imageView.setLayoutParams(layoutParams2);
            imageView.setImageResource(R.mipmap.xiangxia2);
            imageViewList.add(imageView);
            imageView.setPadding(context.getResources().getDimensionPixelOffset(R.dimen.x10), , , );
            linearLayout.addView(textView);
            linearLayout.addView(imageView);

            this.addView(linearLayout);
        }
    }

    @Override
    public void onClick(View v) {
        for (int i = ; i < linearLayoutList.size(); i++) {
            if (v.getId() == linearLayoutList.get(i).getId()) {
                imageViewList.get(i).setImageResource(R.mipmap.xiangxia1);
                if (getOnItemClickListener() != null) {
                    onItemClickListener.onItemClick(i);
                }
            } else {
                imageViewList.get(i).setImageResource(R.mipmap.xiangxia2);
            }
        }
    }

    public interface OnItemClickListener {
        void onItemClick(int position);
    }
}
           

用法如下:

1.在xml布局檔案中放入控件:

<HorizontalScrollView
        android:id="@+id/hsv"
        android:layout_width="match_parent"
        android:layout_height="@dimen/x68"
        android:layout_marginTop="@dimen/x2"
        android:background="#ffffff"
        android:scrollbars="none"
        app:layout_constraintTop_toBottomOf="@+id/rg">

        <com.msyds.app.common.widget.MyTabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal" />
    </HorizontalScrollView>
           

2.在Activity或者Fragment中:

@Bind(R.id.tab_layout)
MyTabLayout tabLayout;
           

初始化控件:我這裡用到的是ButterKnife架構沒用過的人可以參考:https://blog.csdn.net/qq77485042/article/details/77751400

3.添加資料和監聽器:

List<String> strings = new ArrayList<>();
        strings.add("區域");
        strings.add("倉庫");
        strings.add("品牌");
        strings.add("開票");
        strings.add("結算");
        strings.add("類型");
        tabLayout.setData(strings);
        tabLayout.setOnItemClickListener(this);
           

4.監聽器回調:

@Override
    public void onItemClick(int position) {
        ToastUtil.show(position + "");
    }
           

以上就完成了控件的使用。

下面分析一下每個步驟:

在初始化的時候拿到螢幕的最大寬度,因為除以4就是每個Tab的寬度:

WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
width = wm.getDefaultDisplay().getWidth();
           

然後就是最核心的,setData()方法了。

在setData()中先建立每個Tab的參數,在這裡我每個Tab用的是一個線性布局。

然後就是每個Tab中的TextView(文字)和ImageView(右側小箭頭圖檔)的參數(設定的都是包裹内容)。

在然後就是周遊傳遞過來得資料集合。(有多少個資料就要建立多少個Tab)

for (int i = ; i < strings.size(); i++) {
            LinearLayout linearLayout = new LinearLayout(context);
            linearLayout.setLayoutParams(layoutParams);
            linearLayout.setGravity(Gravity.CENTER);
            linearLayout.setId(i);
            linearLayout.setOnClickListener(this);
            linearLayoutList.add(linearLayout);

            TextView textView = new TextView(context);
            textView.setText(strings.get(i));
            textView.setLayoutParams(layoutParams2);

            ImageView imageView = new ImageView(context);
            imageView.setLayoutParams(layoutParams2);
            imageView.setImageResource(R.mipmap.xiangxia2);
            imageViewList.add(imageView);
            imageView.setPadding(context.getResources().getDimensionPixelOffset(R.dimen.x10), , , );
            linearLayout.addView(textView);
            linearLayout.addView(imageView);

            this.addView(linearLayout);
        }
           

建立每個Tab的線性布局,設定id,設定點選事件,把linearLayout加入到linearLayout的集合中。

LinearLayout linearLayout = new LinearLayout(context);
            linearLayout.setLayoutParams(layoutParams);
            linearLayout.setGravity(Gravity.CENTER);
            linearLayout.setId(i);
            linearLayout.setOnClickListener(this);
            linearLayoutList.add(linearLayout);
           

建立Tab的文字和右側圖檔并添加到Tab中。

TextView textView = new TextView(context);
            textView.setText(strings.get(i));
            textView.setLayoutParams(layoutParams2);

            ImageView imageView = new ImageView(context);
            imageView.setLayoutParams(layoutParams2);
            imageView.setImageResource(R.mipmap.xiangxia2);
            imageViewList.add(imageView);
            imageView.setPadding(context.getResources().getDimensionPixelOffset(R.dimen.x10), , , );
            linearLayout.addView(textView);
            linearLayout.addView(imageView);
           

把每個Tab添加到父容器中:

this.addView(linearLayout);
           

最後看點選事件:

@Override
    public void onClick(View v) {
        for (int i = ; i < linearLayoutList.size(); i++) {
            if (v.getId() == linearLayoutList.get(i).getId()) {
                imageViewList.get(i).setImageResource(R.mipmap.xiangxia1);
                if (getOnItemClickListener() != null) {
                    onItemClickListener.onItemClick(i);
                }
            } else {
                imageViewList.get(i).setImageResource(R.mipmap.xiangxia2);
            }
        }
    }
           

周遊線性布局集合也就是Tab的集合,判斷點選的Tab是哪一個給與對應的圖檔切換和回調。

以上就是TabLayout的全部邏輯。