1. 程式人生 > >Android自定義控制元件:將ViewPager封裝自己的TabPager控制元件

Android自定義控制元件:將ViewPager封裝自己的TabPager控制元件

用途

最近專案頁面中經常出現諸如下圖的控制元件,如果為每個頁面分別寫一個將會造成非常多的重複程式碼,不利於專案的閱讀和維護,也會使專案變得非常凌亂。所以,對於這種情況我們可以進行一定的抽取,傳入相關資料後自動顯示到控制元件上。

這裡寫圖片描述

思路

由上圖可知,我們需要上面的Tab作為指示,下面是類似輪播圖ViewPager。我們需要實現點選Tab切換到相應輪播圖頁面,同時滾動Page上面的Tab做相應的變化。

此時我們要動態填充上面Tab的內容以及輪播圖的內容。所以我把這兩塊建立了一個組合控制元件。Tab用一條LinearLayout,下面是ViewPager。同時提供資料介面,分別用於傳入Tab和ViewPager內容。

此處Tab分為背景和內容,背景是控制元件統一的,可以封裝在控制元件內部設定,所以我們要傳入文字的相關部分,這裡我使用傳入TextView。

ViewPager的內容,我們封裝在一個Holder中,Holder可以提供顯示內容及其資料。

有了這兩個內容,我們就可以以適當的方e式將內容分別填充到上面的LinearLayout中和ViewPager中。

具體做法及關鍵程式碼

主要涉及的問題

  1. Tab動態加入LinearLayout時佈局問題
  2. Tab的滑動與ViewPager的關聯
主要程式碼

git

呼叫方法及效果

假設我們需要四個Tab
這裡寫圖片描述

    private void initView(){
        //構造Tab
        TextView tab1 = new TextView(MainActivity.this);
        tab1.setText("TAB1");
        TextView tab2 = new TextView(MainActivity.this);
        tab2.setText("TAB2");
        TextView tab3 = new TextView(MainActivity.this
); tab3.setText("TAB3"); TextView tab4 = new TextView(MainActivity.this); tab4.setText("TAB4"); //加入Tab mMySlidingTabPager.addTab(tab1); mMySlidingTabPager.addTab(tab2); mMySlidingTabPager.addTab(tab3); mMySlidingTabPager.addTab(tab4); //建立頁面holder ViewHolder1 holder1 = new ViewHolder1(); ViewHolder2 holder2 = new ViewHolder2(); ViewHolder3 holder3 = new ViewHolder3(); ViewHolder4 holder4 = new ViewHolder4(); //加入頁面holder mMySlidingTabPager.addHolder(holder1); mMySlidingTabPager.addHolder(holder2); mMySlidingTabPager.addHolder(holder3); mMySlidingTabPager.addHolder(holder4); //頁面填充 這裡就可以顯示啦!!! mMySlidingTabPager.start(); }
ViewHolder
/**
 * 自繪控制元件封裝類
 * Created by vonchenchen on 2015/11/3 0003.
 */
public abstract class BaseWidgetHolder<T> {

    protected View mRootView;

    public abstract View initView();
    public abstract void refreshView(T data);

    public BaseWidgetHolder(){
        mRootView = initView();
        mRootView.setTag(this);
    }

    public View getRootView(){
        return mRootView;
    }
}
控制元件實現
/**
 * Created by vonchenchen on 2015/11/19 0019.
 */
public class MySlidingTabPager extends RelativeLayout{

    private Context mCtx;
    /** Tab佈局 */
    private LinearLayout mTabsLayout;
    /** ViewPager */
    private ViewPager mContentViewPager;

    private List<TextView> mTabList;
    private List<BaseWidgetHolder> mHolderList;

    private MyPagerAdapter mMyPagerAdapter;

    private int mRecordPosition = -1;

    public MySlidingTabPager(Context context) {
        super(context);
        this.mCtx = context;
    }

    public MySlidingTabPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mCtx = context;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        View.inflate(mCtx, R.layout.layout_slidingtabpager, this);
        mTabsLayout = (LinearLayout) findViewById(R.id.ll_tabs);
        mContentViewPager = (ViewPager) findViewById(R.id.vp_content);

        mTabList = new ArrayList<TextView>();
        mHolderList = new ArrayList<BaseWidgetHolder>();

        //監聽ViewPager滾動
        mContentViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                //ViewPager滑動 對應Tab選擇
                updateTab(position, false);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    /**
     * 新增Tab
     * @param tab
     */
    public void addTab(TextView tab){
        mTabList.add(tab);
    }

    /**
     * 新增holder
     * @param holder
     */
    public void addHolder(BaseWidgetHolder holder){
        mHolderList.add(holder);
    }

    /**
     * 開啟顯示
     */
    public void start(){
        initTabView();
        initViewPager();
    }

    private void initTabView(){
        //設定Layout引數,用於新增新的Tab
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, dip2px(MyApplication.getContext(), 40));
        params.weight = 1;

        for(int i=0; i<mTabList.size(); i++){

            TextView view = mTabList.get(i);
            view.setGravity(Gravity.CENTER);

            final int position = i;
            view.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    mContentViewPager.setCurrentItem(position);
                    updateTab(position, true);
                }
            });
            //將TextView加入到LinearLayout上
            mTabsLayout.addView(view, params);
            setViewUnSelected(view, i);
        }

        //初始化預設Tab顏色及其位置
        mRecordPosition = 0;
        setViewSelectd(mTabList.get(0), 0);
    }

    private void updateTab(int position, boolean isTouchTab){
        if(position != mRecordPosition){
            setViewSelectd(mTabList.get(position), position);
        }

        if(mRecordPosition >= 0 && !isTouchTab){
            setViewUnSelected(mTabList.get(mRecordPosition), mRecordPosition);
        }

        mRecordPosition = position;
    }

    /**
     * 當Pager被選擇時設定對應Tab的顏色
     * @param view
     * @param position
     */
    private void setViewSelectd(View view, int position){
        if(position == 0){
            view.setBackgroundResource(R.drawable.shape_detail_rb_left_blue);
        }else if(position == mTabList.size()-1){
            view.setBackgroundResource(R.drawable.shape_detail_rb_right_blue);
        }else{
            view.setBackgroundResource(R.drawable.shape_detail_rb_mid_blue);
        }
    }

    /**
     * 取消Tab的選中顏色
     * @param view
     * @param position
     */
    private void setViewUnSelected(View view, int position){
        if(position == 0) {
            view.setBackgroundResource(R.drawable.shape_detail_rb_left_white);
        }else if(position == mTabList.size()-1){
            view.setBackgroundResource(R.drawable.shape_detail_rb_right_white);
        }else{
            view.setBackgroundResource(R.drawable.shape_detail_rb_mid_white);
        }
    }

    private void initViewPager(){
        mMyPagerAdapter = new MyPagerAdapter();
        mContentViewPager.setAdapter(mMyPagerAdapter);
    }

    public class MyPagerAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return mTabList.size();
        }
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view==object;
        }
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View)object);
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            container.addView(mHolderList.get(position).getRootView());
            return mHolderList.get(position).getRootView();
        }
    }

    private int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale);
    }
}