欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

Android 快速實現(xiàn) ViewPager 滑動頁卡切換(可用作整個 app上導(dǎo)航)

2015-05-11 11:31:09 1639瀏覽

我記得在前面,我寫了一篇Android 微信6.1 tab欄圖標(biāo)和字體顏色漸變的實現(xiàn),如果大家僅僅認(rèn)為這篇文章的功能只是模仿微信顏色漸變效果,那就大錯特錯了!認(rèn)真閱讀了這篇文章的朋友,應(yīng)該知道,這里面代碼可用作 app 通用的底部欄導(dǎo)航,通過它能快速的實現(xiàn)類似微信6.0版本以底部導(dǎo)航的 app 整體架構(gòu),并且在 MainActivity 中需要編寫的代碼非常簡潔。如果有興趣的朋友可以去看看。




效果:

今天這篇 blog的內(nèi)容同樣可以拿來做 app 的整體架構(gòu),但與前面那篇 blog 不同,不同之處是前面那篇文章所講的內(nèi)容可用作底部導(dǎo)航,而這篇 blog 的內(nèi)容,是用作頂部導(dǎo)航,老版本的微信就是此效果,ok,來看看效果圖

實現(xiàn)原理

根據(jù)效果圖,不難分析,可以通過自定義 ViewGroup 來實現(xiàn),但這樣代碼量偏多,看了我的前面 blog 的朋友應(yīng)該清楚,這里最好的實現(xiàn)方式是通過重寫 LinearLayout,相比通過 ViewGroup 來實現(xiàn),省略了測量onMeasure()和布局onLayout()方法的實現(xiàn),因為這些LinearLayout已經(jīng)幫我們實現(xiàn)好了,而我們真正要做的就是為 LinearLayout 填充內(nèi)容,填充內(nèi)容可大致可分為以下四個步驟:

1、填充每個 item 的內(nèi)容

2、繪制每個 item 之間的分割線

3、繪制底部線條

4、繪制指示器的內(nèi)容

代碼實現(xiàn)

1、先把需要用的屬性定義出來
需要的屬性
1
、頁卡指示器的顏色
2
、分割線的顏色
3
、底部線條的顏色
4
、頁卡指示器的高度
5
、分割線距離上下邊距的距離
6
、分割線的寬度

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="indicatorColor" format="color"/>
    <attr name="dividerColor" format="color"/>
    <attr name="bottomLineColor" format="color"/>
    <attr name="dividerMargin" format="dimension"/>
    <attr name="indicatorHeight" format="dimension"/>
    <attr name="bottomLineHeight" format="dimension"/>
    <attr name="dividerWidth" format="dimension"/>
    <declare-styleable name="SlidingTabLayout">
        <attr name="indicatorColor"/>
        <attr name="dividerColor"/>
        <attr name="bottomLineColor"/>
        <attr name="dividerMargin"/>
        <attr name="indicatorHeight"/>
        <attr name="bottomLineHeight"/>
        <attr name="dividerWidth"/>
    </declare-styleable>
</resources>

2、代碼中獲取屬性,并附上相應(yīng)的默認(rèn)值

    /*默認(rèn)的頁卡顏色*/
    private final int DEFAULT_INDICATOR_COLOR = 0xffff00ff;
    /*默認(rèn)分割線的顏色*/
    private final int DEFAULT_DIVIDER_COLOR = 0xff000000;
    /*默認(rèn)title字體的大小*/
    private final int DEFAULT_TEXT_SIZE = 16;
    /*默認(rèn)padding*/
    private final int DEFAULT_TEXT_PADDING = 16;
    /*divider默認(rèn)的寬度*/
    private final int DEFAULT_DIVIDER_WIDTH = 1;
    /*indicator 的高度*/
    private final int DEFAULT_INDICATOR_HEIGHT = 5;
    /*底部線條的高度默認(rèn)值*/
    private final int DEFAULT_BOTTOM_LINE_HEIGHT = 2;
    /*分割線距離上下邊緣的距離默認(rèn)為8*/
    private final int DEFAULT_DIVIDER_MARGIN = 8;
    /*底部線條的顏色默認(rèn)值*/
    private final int DEFAULT_BOTTOM_LINE_COLOR = 0xff000000;
        /*獲取TypedArray*/
        TypedArray typedArray = getResources().obtainAttributes(attrs, R.styleable.SlidingTabLayout);
        /*獲取自定義屬性的個數(shù)*/
        int N = typedArray.getIndexCount();
        Log.v("zgy","=========getIndexCount========="+N) ;
        for (int i = 0; i < N; i++) {
            int attr = typedArray.getIndex(i);
            switch (attr) {
                case R.styleable.SlidingTabLayout_indicatorColor:
                    /*獲取頁卡顏色值*/
                    mIndicatorColor = typedArray.getColor(attr, DEFAULT_INDICATOR_COLOR);
                    break;
                case R.styleable.SlidingTabLayout_dividerColor:
                    /*獲取分割線顏色的值*/
                    mDividerColor = typedArray.getColor(attr, DEFAULT_DIVIDER_COLOR);
                    break;
                case R.styleable.SlidingTabLayout_bottomLineColor:
                    /*獲取底部線條顏色的值*/
                    mBottomLineColor = typedArray.getColor(attr, DEFAULT_BOTTOM_LINE_COLOR);
                    break;
                case R.styleable.SlidingTabLayout_dividerMargin:
                    /*獲取分割線的距離上線邊距的距離*/
                    mDividerMargin = (int) typedArray.getDimension(attr, DEFAULT_DIVIDER_MARGIN * getResources().getDisplayMetrics().density);
                    Log.v("zgy","=========mDividerMargin========="+mDividerMargin) ;
                    break;
                case R.styleable.SlidingTabLayout_indicatorHeight:
                    /*獲取頁卡的高度*/
                    mIndicatorHeight = (int) typedArray.getDimension(attr, DEFAULT_INDICATOR_HEIGHT * getResources().getDisplayMetrics().density);
                    break;
                case R.styleable.SlidingTabLayout_bottomLineHeight:
                    /*獲取底部線條的高度*/
                    mBottomLineHeight = (int) typedArray.getDimension(attr, DEFAULT_BOTTOM_LINE_HEIGHT * getResources().getDisplayMetrics().density);
                    break;
                case R.styleable.SlidingTabLayout_dividerWidth:
                    /*獲取分割線的寬度*/
                    mDividerWidth = (int) typedArray.getDimension(attr, DEFAULT_DIVIDER_WIDTH * getResources().getDisplayMetrics().density);
                    break;
            }
        }
        /*釋放TypedArray*/
        typedArray.recycle();

這里說一個細(xì)節(jié),我經(jīng)常在這里獲取屬性的時候習(xí)慣性的把

case R.styleable.SlidingTabLayout_indicatorColor:

寫成

case R.attr.indicatorColor:

而且這里不會報錯,不過結(jié)果可想而知,無法獲取我們設(shè)置的屬性內(nèi)容,這里如果有跟我犯同樣錯誤的朋友記得注意一下。

3、為 LinearLayout 填充內(nèi)容

    /**
     * 設(shè)置viewPager,初始化SlidingTab,
     * 在這個方法中為SlidingLayout設(shè)置
     * 內(nèi)容,
     *
     * @param viewPager
     */
    public void setViewPager(ViewPager viewPager) {
        /*先移除所以已經(jīng)填充的內(nèi)容*/
        removeAllViews();
        /* viewPager 不能為空*/
        if (viewPager == null) {
            throw new RuntimeException("ViewPager不能為空");
        }
        mViewPager = viewPager;
        mViewPager.setOnPageChangeListener(new InternalViewPagerChange());
        //填充內(nèi)容
        populateTabLayout();
    }
    /**
     * 填充layout,設(shè)置其內(nèi)容
     */
    private void populateTabLayout() {
        final PagerAdapter adapter = mViewPager.getAdapter();
        final OnClickListener tabOnClickListener = new TabOnClickListener();
        mItemName = (TabItemName) adapter;
        for (int i = 0; i < adapter.getCount(); i++) {
            TextView textView = createDefaultTabView(getContext());
            textView.setOnClickListener(tabOnClickListener);
            textView.setText(mItemName.getTabName(i));
            addView(textView);
        }
    }

根據(jù)ViewPager中頁面的個數(shù),填充相應(yīng)的 tab。

4、繪制相應(yīng)的內(nèi)容
繪制內(nèi)容,肯定在 onDraw()方法中
繪制底部線條

canvas.drawRect(0,height - mBottomLineHeight,getWidth(),height,mBottomPaint);

繪制分割線

 for (int i = 0; i < getChildCount() - 1; i++) {
      View child = getChildAt(i);
      canvas.drawLine(child.getRight(), mDividerMargin,child.getRight(), height - mDividerMargin,mDividerPaint);
        }

重點(diǎn):繪制滑動頁卡

        /*當(dāng)前頁面的View tab*/
        View selectView = getChildAt(mSelectedPosition);
        /*計算開始繪制的位置*/
        int left = selectView.getLeft();
        /*計算結(jié)束繪制的位置*/
        int right = selectView.getRight();
        if (mSelectionOffset > 0) {
            View nextView = getChildAt(mSelectedPosition + 1);
            /*如果有偏移量,重新計算開始繪制的位置*/
            left = (int) (mSelectionOffset * nextView.getLeft() + (1.0f - mSelectionOffset) * left);
            /*如果有偏移量,重新計算結(jié)束繪制的位置*/
            right = (int) (mSelectionOffset * nextView.getRight() + (1.0f - mSelectionOffset) * right);
        }
        /*繪制滑動的頁卡*/
        canvas.drawRect(left, height - mIndicatorHeight, right, height, mIndicatorPaint);

運(yùn)用案例

為了體現(xiàn)他的簡潔之處,這里把 xml 中的代碼也貼出來

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"               xmlns:tools="http://schemas.android.com/tools"               xmlns:zgy="http://schemas.android.com/apk/res-auto"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context=".MainActivity">
    <demo.slidingtablayout.view.SlidingTabLayout
        android:id="@+id/id_tab"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        zgy:bottomLineColor="#AEAEAE"
        zgy:dividerMargin="15dp"
        zgy:indicatorColor="#77e69c"
        zgy:indicatorHeight="5dp"
        zgy:bottomLineHeight="2dp"
        android:background="#eeeeee">
    </demo.slidingtablayout.view.SlidingTabLayout>
 
    <android.support.v4.view.ViewPager
        android:layout_below="@+id/id_tab"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/id_view_pager"/>
</RelativeLayout>

MainActivity.java

public class MainActivity extends ActionBarActivity {
 
    /*viewPager*/
    private ViewPager mViewPager ;
    /*自定義的 tabLayout*/
    private SlidingTabLayout mTabLayout ;
    /*每個 tab  item*/
    private List<PagerItem> mTab = new ArrayList<>() ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mViewPager = (ViewPager) findViewById(R.id.id_view_pager) ;
        mTabLayout = (SlidingTabLayout) findViewById(R.id.id_tab) ;
        mTab.add(new PagerItem("tab1","FirstPager")) ;
        mTab.add(new PagerItem("tab2","SecondPager")) ;
        mTab.add(new PagerItem("tab3","ThirdPager")) ;
        mTab.add(new PagerItem("tab4","FourthPager")) ;
        mViewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
        /*需要先為 viewpager 設(shè)置 adapter*/
        mTabLayout.setViewPager(mViewPager);
    }
 
 private class ViewPagerAdapter extends FragmentPagerAdapter implements SlidingTabLayout.TabItemName{
 
        public ViewPagerAdapter(FragmentManager fm) {
            super(fm);
        }
 
        @Override
        public Fragment getItem(int position) {
            return mTab.get(position).createFragment();
        }
 
        @Override
        public int getCount() {
            return mTab.size();
        }
 
        @Override
        public String getTabName(int position) {
            return mTab.get(position).getTitle();
        }
    }
}


標(biāo)簽:

熱門專區(qū)

暫無熱門資訊

課程推薦

微信
微博
15311698296

全國免費(fèi)咨詢熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權(quán)所有   北京市海淀區(qū)寶盛北里西區(qū)28號中關(guān)村智誠科創(chuàng)大廈4層
京ICP備2021002079號-2   Copyright ? 2017 - 2022
返回頂部 返回頂部