Android 高仿微信6.0主界面 帶你玩轉切換圖標變色


轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/41087219,本文出自:【張鴻洋的博客】

1、概述

學習Android少不了模仿各種app的界面,自從微信6.0問世以后,就覺得微信切換時那個變色的Tab圖標屌屌的,今天我就帶大家自定義控件,帶你變色變得飛起~~

好了,下面先看下效果圖:


清晰度不太好,大家湊合看~~有木有覺得這個顏色弱爆了了的,,,下面我動動手指給你換個顏色:


有沒有這個顏色比較妖一點~~~好了~下面開始介紹原理。

2、原理介紹

通過上面的效果圖,大家可能也猜到了,我們的圖標並非是兩張圖片,而是一張圖,並且目標顏色是可定制的,誰讓現在動不動就談個性化呢。

那么我們如何做到,可以讓圖標隨心所遇的變色了,其實原理,在我的博客中出現了很多次了,下面你將看到一張熟悉的圖:


有沒有很熟悉的感腳,我們實際上還是利用了Paint的Xfermode,這次我們使用的是:Mode.DST_IN

Dst_IN回顧一下什么效果,先繪制Dst,設置Mode,再繪制Src,則顯示的是先后繪圖的交集區域,且是Dst.

再仔細觀察下我們的圖標:


為了方便大家的觀看,我特意拿ps選擇了一下我們圖標的非透明區域,可以看到,我們這個小機器人非透明區域就是被線框起來的部分。

然后,我們圖標變色的原理就出現了:

1、先繪制一個顏色(例如:粉紅)

2、設置Mode=DST_IN

3、繪制我們這個可愛的小機器人

回答我,顯示什么,是不是顯示交集,交集是什么?交集是我們的小機器人的非透明區域,也就是那張臉,除了兩個眼;

好了,那怎么變色呢?

我繪制一個顏色的時候,難道不能設置alpha么~~~

到此,大家應該已經了解了我們圖標的繪制的原理了吧。

如果你對Mode不熟悉:建議移步至:Android 自定義控件實現刮刮卡效果 真的就只是刮刮卡么


3、自定義圖標控件

我們的整個界面不用說,是ViewPager+Fragment ,現在關注的是底部~~

接下來我們考慮,底部的Tab,Tab我們的布局是LinearLayout,內部四個View,通過設置weight達到均分~~

這個View就是我們的自定義的圖標控件了,我們叫做:ChangeColorIconWithTextView

接下來考慮,應該有什么屬性公布出來

1、自定義屬性

想了一下,我決定把圖標,圖標顏色,圖標下顯示的文字,文字大小這四個屬性作為自定義屬性。

那就自定義屬性走起了:

a、values/attr.xml

[java] view plain copy print?
  1. <?xml version=“1.0” encoding=“utf-8”?>  
  2. <resources>  
  3.   
  4.     <attr name=”icon” format=“reference” />  
  5.     <attr name=”color” format=“color” />  
  6.     <attr name=”text” format=“string” />  
  7.     <attr name=”text_size” format=“dimension” />  
  8.   
  9.     <declare-styleable name=”ChangeColorIconView”>  
  10.         <attr name=”icon” />  
  11.         <attr name=”color” />  
  12.         <attr name=”text” />  
  13.         <attr name=”text_size” />  
  14.     </declare-styleable>  
  15.   
  16. </resources>  
<?xml version="1.0" encoding="utf-8"?><resources>

<attr name="icon" format="reference" />
<attr name="color" format="color" />
<attr name="text" format="string" />
<attr name="text_size" format="dimension" />

<declare-styleable name="ChangeColorIconView">
<attr name="icon" />
<attr name="color" />
<attr name="text" />
<attr name="text_size" />
</declare-styleable>

</resources>

b、在布局文件中使用

[html] view plain copy print?
  1. <com.zhy.weixin6.ui.ChangeColorIconWithTextView  
  2.            android:id=“@+id/id_indicator_one”  
  3.            android:layout_width=“0dp”  
  4.            android:layout_height=“fill_parent”  
  5.            android:layout_weight=“1”  
  6.            android:padding=“5dp”  
  7.            zhy:icon=“@drawable/ic_menu_start_conversation”  
  8.            zhy:text=“@string/tab_weixin”  
  9.            zhy:text_size=“12sp” />  
 <com.zhy.weixin6.ui.ChangeColorIconWithTextView            android:id="@+id/id_indicator_one"            android:layout_width="0dp"            android:layout_height="fill_parent"            android:layout_weight="1"            android:padding="5dp"            zhy:icon="@drawable/ic_menu_start_conversation"            zhy:text="@string/tab_weixin"            zhy:text_size="12sp" />

自己注意命名空間的寫法,xmlns:zhy=”http://schemas.android.com/apk/res/應用的包名”。

c、在構造方法中獲取

[java] view plain copy print?
  1. public class ChangeColorIconWithTextView extends View  
  2. {  
  3.   
  4.     private Bitmap mBitmap;  
  5.     private Canvas mCanvas;  
  6.     private Paint mPaint;  
  7.     /** 
  8.      * 顏色 
  9.      */  
  10.     private int mColor = 0xFF45C01A;  
  11.     /** 
  12.      * 透明度 0.0-1.0 
  13.      */  
  14.     private float mAlpha = 0f;  
  15.     /** 
  16.      * 圖標 
  17.      */  
  18.     private Bitmap mIconBitmap;  
  19.     /** 
  20.      * 限制繪制icon的范圍 
  21.      */  
  22.     private Rect mIconRect;  
  23.     /** 
  24.      * icon底部文本 
  25.      */  
  26.     private String mText = “微信”;  
  27.     private int mTextSize = (int) TypedValue.applyDimension(  
  28.             TypedValue.COMPLEX_UNIT_SP, 10, getResources().getDisplayMetrics());  
  29.     private Paint mTextPaint;  
  30.     private Rect mTextBound = new Rect();  
  31.   
  32.     public ChangeColorIconWithTextView(Context context)  
  33.     {  
  34.         super(context);  
  35.     }  
  36.   
  37.     /** 
  38.      * 初始化自定義屬性值 
  39.      *  
  40.      * @param context 
  41.      * @param attrs 
  42.      */  
  43.     public ChangeColorIconWithTextView(Context context, AttributeSet attrs)  
  44.     {  
  45.         super(context, attrs);  
  46.   
  47.         // 獲取設置的圖標  
  48.         TypedArray a = context.obtainStyledAttributes(attrs,  
  49.                 R.styleable.ChangeColorIconView);  
  50.   
  51.         int n = a.getIndexCount();  
  52.         for (int i = 0; i < n; i++)  
  53.         {  
  54.   
  55.             int attr = a.getIndex(i);  
  56.             switch (attr)  
  57.             {  
  58.             case R.styleable.ChangeColorIconView_icon:  
  59.                 BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr);  
  60.                 mIconBitmap = drawable.getBitmap();  
  61.                 break;  
  62.             case R.styleable.ChangeColorIconView_color:  
  63.                 mColor = a.getColor(attr, 0x45C01A);  
  64.                 break;  
  65.             case R.styleable.ChangeColorIconView_text:  
  66.                 mText = a.getString(attr);  
  67.                 break;  
  68.             case R.styleable.ChangeColorIconView_text_size:  
  69.                 mTextSize = (int) a.getDimension(attr, TypedValue  
  70.                         .applyDimension(TypedValue.COMPLEX_UNIT_SP, 10,  
  71.                                 getResources().getDisplayMetrics()));  
  72.                 break;  
  73.   
  74.             }  
  75.         }  
  76.   
  77.         a.recycle();  
  78.   
  79.         mTextPaint = new Paint();  
  80.         mTextPaint.setTextSize(mTextSize);  
  81.         mTextPaint.setColor(0xff555555);  
  82.         // 得到text繪制范圍  
  83.         mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);  
  84.   
  85.     }  
public class ChangeColorIconWithTextView extends View{    private Bitmap mBitmap;    private Canvas mCanvas;    private Paint mPaint;    /**     * 顏色     */    private int mColor = 0xFF45C01A;    /**     * 透明度 0.0-1.0     */    private float mAlpha = 0f;    /**     * 圖標     */    private Bitmap mIconBitmap;    /**     * 限制繪制icon的范圍     */    private Rect mIconRect;    /**     * icon底部文本     */    private String mText = "微信";    private int mTextSize = (int) TypedValue.applyDimension(            TypedValue.COMPLEX_UNIT_SP, 10, getResources().getDisplayMetrics());    private Paint mTextPaint;    private Rect mTextBound = new Rect();    public ChangeColorIconWithTextView(Context context)    {        super(context);    }    /**     * 初始化自定義屬性值     *      * @param context     * @param attrs     */    public ChangeColorIconWithTextView(Context context, AttributeSet attrs)    {        super(context, attrs);        // 獲取設置的圖標        TypedArray a = context.obtainStyledAttributes(attrs,                R.styleable.ChangeColorIconView);        int n = a.getIndexCount();        for (int i = 0; i < n; i++)        {            int attr = a.getIndex(i);            switch (attr)            {            case R.styleable.ChangeColorIconView_icon:                BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr);                mIconBitmap = drawable.getBitmap();                break;            case R.styleable.ChangeColorIconView_color:                mColor = a.getColor(attr, 0x45C01A);                break;            case R.styleable.ChangeColorIconView_text:                mText = a.getString(attr);                break;            case R.styleable.ChangeColorIconView_text_size:                mTextSize = (int) a.getDimension(attr, TypedValue                        .applyDimension(TypedValue.COMPLEX_UNIT_SP, 10,                                getResources().getDisplayMetrics()));                break;            }        }        a.recycle();        mTextPaint = new Paint();        mTextPaint.setTextSize(mTextSize);        mTextPaint.setColor(0xff555555);        // 得到text繪制范圍        mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);    }

可以看到,我們在構造方法中獲取了自定義的屬性,並且計算了文本占據的控件存在我們的mTextBound中。

2、圖標的繪制區域的選擇

我們考慮下,有了屬性,我們需要繪制一個文本,文本之上一個圖標,我們怎么去控制繪制的區域呢?
我們的View顯示區域,無非以下三種情況:


針對這三種情況,我門的圖標的邊長應該是什么呢?

我覺得邊長應該是:控件的高度-文本的高度-內邊距   與  控件的寬度-內邊距  兩者的小值;大家仔細推敲一下;

好了,有了上面的邊長的結論,我們就開始計算圖標的繪制范圍了:

[java] view plain copy print?
  1. @Override  
  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  
  3. {  
  4.     super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  5.   
  6.     // 得到繪制icon的寬  
  7.     int bitmapWidth = Math.min(getMeasuredWidth() - getPaddingLeft()  
  8.             - getPaddingRight(), getMeasuredHeight() - getPaddingTop()  
  9.             - getPaddingBottom() - mTextBound.height());  
  10.   
  11.     int left = getMeasuredWidth() / 2 - bitmapWidth / 2;  
  12.     int top = (getMeasuredHeight() - mTextBound.height()) / 2 - bitmapWidth  
  13.             / 2;  
  14.     // 設置icon的繪制范圍  
  15.     mIconRect = new Rect(left, top, left + bitmapWidth, top + bitmapWidth);  
  16.   
  17. }  
  @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)    {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        // 得到繪制icon的寬        int bitmapWidth = Math.min(getMeasuredWidth() - getPaddingLeft()                - getPaddingRight(), getMeasuredHeight() - getPaddingTop()                - getPaddingBottom() - mTextBound.height());        int left = getMeasuredWidth() / 2 - bitmapWidth / 2;        int top = (getMeasuredHeight() - mTextBound.height()) / 2 - bitmapWidth                / 2;        // 設置icon的繪制范圍        mIconRect = new Rect(left, top, left + bitmapWidth, top + bitmapWidth);    }

3、繪制圖標

繪制圖標有很多步驟呀,我來列一列

1、計算alpha(默認為0)

2、繪制原圖

3、在繪圖區域,繪制一個純色塊(設置了alpha),此步繪制在內存的bitmap上

4、設置mode,針對內存中的bitmap上的paint

5、繪制我們的圖標,此步繪制在內存的bitmap上

6、繪制原文本

7、繪制設置alpha和顏色后的文本

8、將內存中的bitmap繪制出來

根據上面的步驟,可以看出來,我們的圖標其實繪制了兩次,為什么要繪制原圖呢,因為我覺得比較好看。

3-5步驟,就是我們上面分析的原理

6-7步,是繪制文本,可以看到,我們的文本就是通過設置alpha實現的

[java] view plain copy print?
  1. @Override  
  2.     protected void onDraw(Canvas canvas)  
  3.     {  
  4.   
  5.         int alpha = (int) Math.ceil((255 * mAlpha));  
  6.         canvas.drawBitmap(mIconBitmap, null, mIconRect, null);  
  7.         setupTargetBitmap(alpha);  
  8.         drawSourceText(canvas, alpha);  
  9.         drawTargetText(canvas, alpha);  
  10.         canvas.drawBitmap(mBitmap, 00null);  
  11.   
  12.     }  
  13.       
  14.     private void setupTargetBitmap(int alpha)  
  15.     {  
  16.         mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),  
  17.                 Config.ARGB_8888);  
  18.         mCanvas = new Canvas(mBitmap);  
  19.         mPaint = new Paint();  
  20.         mPaint.setColor(mColor);  
  21.         mPaint.setAntiAlias(true);  
  22.         mPaint.setDither(true);  
  23.         mPaint.setAlpha(alpha);  
  24.         mCanvas.drawRect(mIconRect, mPaint);  
  25.         mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));  
  26.         mPaint.setAlpha(255);  
  27.         mCanvas.drawBitmap(mIconBitmap, null, mIconRect, mPaint);  
  28.     }  
  29.   
  30.     private void drawSourceText(Canvas canvas, int alpha)  
  31.     {  
  32.         mTextPaint.setTextSize(mTextSize);  
  33.         mTextPaint.setColor(0xff333333);  
  34.         mTextPaint.setAlpha(255 - alpha);  
  35.         canvas.drawText(mText, mIconRect.left + mIconRect.width() / 2  
  36.                 - mTextBound.width() / 2,  
  37.                 mIconRect.bottom + mTextBound.height(), mTextPaint);  
  38.     }  
  39.       
  40.     private void drawTargetText(Canvas canvas, int alpha)  
  41.     {  
  42.         mTextPaint.setColor(mColor);  
  43.         mTextPaint.setAlpha(alpha);  
  44.         canvas.drawText(mText, mIconRect.left + mIconRect.width() / 2  
  45.                 - mTextBound.width() / 2,  
  46.                 mIconRect.bottom + mTextBound.height(), mTextPaint);  
  47.           
  48.     }  
@Override    protected void onDraw(Canvas canvas)    {        int alpha = (int) Math.ceil((255 * mAlpha));        canvas.drawBitmap(mIconBitmap, null, mIconRect, null);        setupTargetBitmap(alpha);        drawSourceText(canvas, alpha);        drawTargetText(canvas, alpha);        canvas.drawBitmap(mBitmap, 0, 0, null);    }    private void setupTargetBitmap(int alpha)    {        mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),                Config.ARGB_8888);        mCanvas = new Canvas(mBitmap);        mPaint = new Paint();        mPaint.setColor(mColor);        mPaint.setAntiAlias(true);        mPaint.setDither(true);        mPaint.setAlpha(alpha);        mCanvas.drawRect(mIconRect, mPaint);        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));        mPaint.setAlpha(255);        mCanvas.drawBitmap(mIconBitmap, null, mIconRect, mPaint);    }    private void drawSourceText(Canvas canvas, int alpha)    {        mTextPaint.setTextSize(mTextSize);        mTextPaint.setColor(0xff333333);        mTextPaint.setAlpha(255 - alpha);        canvas.drawText(mText, mIconRect.left + mIconRect.width() / 2                - mTextBound.width() / 2,                mIconRect.bottom + mTextBound.height(), mTextPaint);    }    private void drawTargetText(Canvas canvas, int alpha)    {        mTextPaint.setColor(mColor);        mTextPaint.setAlpha(alpha);        canvas.drawText(mText, mIconRect.left + mIconRect.width() / 2                - mTextBound.width() / 2,                mIconRect.bottom + mTextBound.height(), mTextPaint);    }

關於繪制文本區域的計算,首先是起點x:mIconRect.left + mIconRect.width() / 2- mTextBound.width() / 2 有點長哈,文本mIconRect.left + mIconRect.width() / 2這個位置,在圖標水平區域的中心點,這個應該沒有疑問;圖標水平區域的中點- mTextBound.width() / 2 開始繪制文本,是不是就是居中在圖標的下面;

有人可能會問:你怎么知道文本寬度小於圖標,我有5個字咋辦?5個字怎么了,照樣是居中顯示,不信你試試~~

4、公布設置透明度的方法

到此,我們的圖標控件寫完了,但是還沒有把我們的控制icon的方法放出去:

[java] view plain copy print?
  1. public void setIconAlpha(float alpha)  
  2. {  
  3.     this.mAlpha = alpha;  
  4.     invalidateView();  
  5. }  
  6.   
  7. private void invalidateView()  
  8. {  
  9.     if (Looper.getMainLooper() == Looper.myLooper())  
  10.     {  
  11.         invalidate();  
  12.     } else  
  13.     {  
  14.         postInvalidate();  
  15.     }  
  16. }  
  public void setIconAlpha(float alpha)    {        this.mAlpha = alpha;        invalidateView();    }    private void invalidateView()    {        if (Looper.getMainLooper() == Looper.myLooper())        {            invalidate();        } else        {            postInvalidate();        }    }

我們叫做setIconAlpha,避免了和setAlpha沖突,設置完成后,invalidate一下~~~


到此就真的結束了,接下來看用法。


4、實戰


1、布局文件

[html] view plain copy print?
  1. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”  
  2.     xmlns:zhy=“http://schemas.android.com/apk/res/com.zhy.weixin6.ui”  
  3.     xmlns:tools=“http://schemas.android.com/tools”  
  4.     android:layout_width=“match_parent”  
  5.     android:layout_height=“match_parent”  
  6.     android:orientation=“vertical” >  
  7.   
  8.     <android.support.v4.view.ViewPager  
  9.         android:id=“@+id/id_viewpager”  
  10.         android:layout_width=“fill_parent”  
  11.         android:layout_height=“0dp”  
  12.         android:layout_weight=“1” >  
  13.     </android.support.v4.view.ViewPager>  
  14.   
  15.     <LinearLayout  
  16.         android:layout_width=“fill_parent”  
  17.         android:layout_height=“60dp”  
  18.         android:background=“@drawable/tabbg”  
  19.         android:orientation=“horizontal” >  
  20.   
  21.         <com.zhy.weixin6.ui.ChangeColorIconWithTextView  
  22.             android:id=“@+id/id_indicator_one”  
  23.             android:layout_width=“0dp”  
  24.             android:layout_height=“fill_parent”  
  25.             android:layout_weight=“1”  
  26.             android:padding=“5dp”  
  27.             zhy:icon=“@drawable/ic_menu_start_conversation”  
  28.             zhy:text=“@string/tab_weixin”  
  29.             zhy:text_size=“12sp” />  
  30.   
  31.         <com.zhy.weixin6.ui.ChangeColorIconWithTextView  
  32.             android:id=“@+id/id_indicator_two”  
  33.             android:layout_width=“0dp”  
  34.             android:layout_height=“fill_parent”  
  35.             android:layout_weight=“1”  
  36.             android:padding=“5dp”  
  37.             zhy:icon=“@drawable/ic_menu_friendslist”  
  38.             zhy:text=“@string/tab_contact”  
  39.             zhy:text_size=“12sp” />  
  40.   
  41.         <com.zhy.weixin6.ui.ChangeColorIconWithTextView  
  42.             android:id=“@+id/id_indicator_three”  
  43.             android:layout_width=“0dp”  
  44.             android:layout_height=“fill_parent”  
  45.             android:layout_weight=“1”  
  46.             android:padding=“5dp”  
  47.             zhy:icon=“@drawable/ic_menu_emoticons”  
  48.             zhy:text=“@string/tab_find”  
  49.             zhy:text_size=“12sp” />  
  50.   
  51.         <com.zhy.weixin6.ui.ChangeColorIconWithTextView  
  52.             android:id=“@+id/id_indicator_four”  
  53.             android:layout_width=“0dp”  
  54.             android:layout_height=“fill_parent”  
  55.             android:layout_weight=“1”  
  56.             android:padding=“5dp”  
  57.             zhy:icon=“@drawable/ic_menu_allfriends”  
  58.             zhy:text=“@string/tab_me”  
  59.             zhy:text_size=“12sp” />  
  60.     </LinearLayout>  
  61.   
  62. </LinearLayout>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:zhy="http://schemas.android.com/apk/res/com.zhy.weixin6.ui"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <android.support.v4.view.ViewPager        android:id="@+id/id_viewpager"        android:layout_width="fill_parent"        android:layout_height="0dp"        android:layout_weight="1" >    </android.support.v4.view.ViewPager>    <LinearLayout        android:layout_width="fill_parent"        android:layout_height="60dp"        android:background="@drawable/tabbg"        android:orientation="horizontal" >        <com.zhy.weixin6.ui.ChangeColorIconWithTextView            android:id="@+id/id_indicator_one"            android:layout_width="0dp"            android:layout_height="fill_parent"            android:layout_weight="1"            android:padding="5dp"            zhy:icon="@drawable/ic_menu_start_conversation"            zhy:text="@string/tab_weixin"            zhy:text_size="12sp" />        <com.zhy.weixin6.ui.ChangeColorIconWithTextView            android:id="@+id/id_indicator_two"            android:layout_width="0dp"            android:layout_height="fill_parent"            android:layout_weight="1"            android:padding="5dp"            zhy:icon="@drawable/ic_menu_friendslist"            zhy:text="@string/tab_contact"            zhy:text_size="12sp" />        <com.zhy.weixin6.ui.ChangeColorIconWithTextView            android:id="@+id/id_indicator_three"            android:layout_width="0dp"            android:layout_height="fill_parent"            android:layout_weight="1"            android:padding="5dp"            zhy:icon="@drawable/ic_menu_emoticons"            zhy:text="@string/tab_find"            zhy:text_size="12sp" />        <com.zhy.weixin6.ui.ChangeColorIconWithTextView            android:id="@+id/id_indicator_four"            android:layout_width="0dp"            android:layout_height="fill_parent"            android:layout_weight="1"            android:padding="5dp"            zhy:icon="@drawable/ic_menu_allfriends"            zhy:text="@string/tab_me"            zhy:text_size="12sp" />    </LinearLayout></LinearLayout>

2、MainActivity

[java] view plain copy print?
  1. package com.zhy.weixin6.ui;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.Method;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7.   
  8. import android.annotation.SuppressLint;  
  9. import android.os.Bundle;  
  10. import android.support.v4.app.Fragment;  
  11. import android.support.v4.app.FragmentActivity;  
  12. import android.support.v4.app.FragmentPagerAdapter;  
  13. import android.support.v4.view.ViewPager;  
  14. import android.support.v4.view.ViewPager.OnPageChangeListener;  
  15. import android.view.Menu;  
  16. import android.view.View;  
  17. import android.view.View.OnClickListener;  
  18. import android.view.ViewConfiguration;  
  19. import android.view.Window;  
  20.   
  21. @SuppressLint(“NewApi”)  
  22. public class MainActivity extends FragmentActivity implements  
  23.         OnPageChangeListener, OnClickListener  
  24. {  
  25.     private ViewPager mViewPager;  
  26.     private List<Fragment> mTabs = new ArrayList<Fragment>();  
  27.     private FragmentPagerAdapter mAdapter;  
  28.   
  29.     private String[] mTitles = new String[] { “First Fragment!”,  
  30.             ”Second Fragment!”“Third Fragment!”“Fourth Fragment!” };  
  31.   
  32.     private List<ChangeColorIconWithTextView> mTabIndicator = new ArrayList<ChangeColorIconWithTextView>();  
  33.   
  34.     @Override  
  35.     protected void onCreate(Bundle savedInstanceState)  
  36.     {  
  37.         super.onCreate(savedInstanceState);  
  38.         setContentView(R.layout.activity_main);  
  39.   
  40.         setOverflowShowingAlways();  
  41.         getActionBar().setDisplayShowHomeEnabled(false);  
  42.         mViewPager = (ViewPager) findViewById(R.id.id_viewpager);  
  43.   
  44.         initDatas();  
  45.   
  46.         mViewPager.setAdapter(mAdapter);  
  47.         mViewPager.setOnPageChangeListener(this);  
  48.     }  
  49.   
  50.     private void initDatas()  
  51.     {  
  52.   
  53.         for (String title : mTitles)  
  54.         {  
  55.             TabFragment tabFragment = new TabFragment();  
  56.             Bundle args = new Bundle();  
  57.             args.putString(”title”, title);  
  58.             tabFragment.setArguments(args);  
  59.             mTabs.add(tabFragment);  
  60.         }  
  61.   
  62.         mAdapter = new FragmentPagerAdapter(getSupportFragmentManager())  
  63.         {  
  64.   
  65.             @Override  
  66.             public int getCount()  
  67.             {  
  68.                 return mTabs.size();  
  69.             }  
  70.   
  71.             @Override  
  72.             public Fragment getItem(int arg0)  
  73.             {  
  74.                 return mTabs.get(arg0);  
  75.             }  
  76.         };  
  77.   
  78.         initTabIndicator();  
  79.   
  80.     }  
  81.   
  82.     @Override  
  83.     public boolean onCreateOptionsMenu(Menu menu)  
  84.     {  
  85.         getMenuInflater().inflate(R.menu.main, menu);  
  86.         return true;  
  87.     }  
  88.   
  89.     private void initTabIndicator()  
  90.     {  
  91.         ChangeColorIconWithTextView one = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_one);  
  92.         ChangeColorIconWithTextView two = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_two);  
  93.         ChangeColorIconWithTextView three = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_three);  
  94.         ChangeColorIconWithTextView four = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_four);  
  95.   
  96.         mTabIndicator.add(one);  
  97.         mTabIndicator.add(two);  
  98.         mTabIndicator.add(three);  
  99.         mTabIndicator.add(four);  
  100.   
  101.         one.setOnClickListener(this);  
  102.         two.setOnClickListener(this);  
  103.         three.setOnClickListener(this);  
  104.         four.setOnClickListener(this);  
  105.   
  106.         one.setIconAlpha(1.0f);  
  107.     }  
  108.   
  109.     @Override  
  110.     public void onPageSelected(int arg0)  
  111.     {  
  112.     }  
  113.   
  114.     @Override  
  115.     public void onPageScrolled(int position, float positionOffset,  
  116.             int positionOffsetPixels)  
  117.     {  
  118.         // Log.e(“TAG”, “position = ” + position + ” , positionOffset = ”  
  119.         // + positionOffset);  
  120.   
  121.         if (positionOffset > 0)  
  122.         {  
  123.             ChangeColorIconWithTextView left = mTabIndicator.get(position);  
  124.             ChangeColorIconWithTextView right = mTabIndicator.get(position + 1);  
  125.   
  126.             left.setIconAlpha(1 - positionOffset);  
  127.             right.setIconAlpha(positionOffset);  
  128.         }  
  129.   
  130.     }  
  131.   
  132.     @Override  
  133.     public void onPageScrollStateChanged(int state)  
  134.     {  
  135.   
  136.     }  
  137.   
  138.     @Override  
  139.     public void onClick(View v)  
  140.     {  
  141.   
  142.         resetOtherTabs();  
  143.   
  144.         switch (v.getId())  
  145.         {  
  146.         case R.id.id_indicator_one:  
  147.             mTabIndicator.get(0).setIconAlpha(1.0f);  
  148.             mViewPager.setCurrentItem(0false);  
  149.             break;  
  150.         case R.id.id_indicator_two:  
  151.             mTabIndicator.get(1).setIconAlpha(1.0f);  
  152.             mViewPager.setCurrentItem(1false);  
  153.             break;  
  154.         case R.id.id_indicator_three:  
  155.             mTabIndicator.get(2).setIconAlpha(1.0f);  
  156.             mViewPager.setCurrentItem(2false);  
  157.             break;  
  158.         case R.id.id_indicator_four:  
  159.             mTabIndicator.get(3).setIconAlpha(1.0f);  
  160.             mViewPager.setCurrentItem(3false);  
  161.             break;  
  162.   
  163.         }  
  164.   
  165.     }  
  166.   
  167.     /** 
  168.      * 重置其他的Tab 
  169.      */  
  170.     private void resetOtherTabs()  
  171.     {  
  172.         for (int i = 0; i < mTabIndicator.size(); i++)  
  173.         {  
  174.             mTabIndicator.get(i).setIconAlpha(0);  
  175.         }  
  176.     }  
  177.   
  178.     @Override  
  179.     public boolean onMenuOpened(int featureId, Menu menu)  
  180.     {  
  181.         if (featureId == Window.FEATURE_ACTION_BAR && menu != null)  
  182.         {  
  183.             if (menu.getClass().getSimpleName().equals(“MenuBuilder”))  
  184.             {  
  185.                 try  
  186.                 {  
  187.                     Method m = menu.getClass().getDeclaredMethod(  
  188.                             ”setOptionalIconsVisible”, Boolean.TYPE);  
  189.                     m.setAccessible(true);  
  190.                     m.invoke(menu, true);  
  191.                 } catch (Exception e)  
  192.                 {  
  193.                 }  
  194.             }  
  195.         }  
  196.         return super.onMenuOpened(featureId, menu);  
  197.     }  
  198.   
  199.     private void setOverflowShowingAlways()  
  200.     {  
  201.         try  
  202.         {  
  203.             // true if a permanent menu key is present, false otherwise.  
  204.             ViewConfiguration config = ViewConfiguration.get(this);  
  205.             Field menuKeyField = ViewConfiguration.class  
  206.                     .getDeclaredField(”sHasPermanentMenuKey”);  
  207.             menuKeyField.setAccessible(true);  
  208.             menuKeyField.setBoolean(config, false);  
  209.         } catch (Exception e)  
  210.         {  
  211.             e.printStackTrace();  
  212.         }  
  213.     }  
  214.   
  215. }  
package com.zhy.weixin6.ui;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;import android.annotation.SuppressLint;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentPagerAdapter;import android.support.v4.view.ViewPager;import android.support.v4.view.ViewPager.OnPageChangeListener;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewConfiguration;import android.view.Window;@SuppressLint("NewApi")public class MainActivity extends FragmentActivity implements        OnPageChangeListener, OnClickListener{    private ViewPager mViewPager;    private List<Fragment> mTabs = new ArrayList<Fragment>();    private FragmentPagerAdapter mAdapter;    private String[] mTitles = new String[] { "First Fragment!",            "Second Fragment!", "Third Fragment!", "Fourth Fragment!" };    private List<ChangeColorIconWithTextView> mTabIndicator = new ArrayList<ChangeColorIconWithTextView>();    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        setOverflowShowingAlways();        getActionBar().setDisplayShowHomeEnabled(false);        mViewPager = (ViewPager) findViewById(R.id.id_viewpager);        initDatas();        mViewPager.setAdapter(mAdapter);        mViewPager.setOnPageChangeListener(this);    }    private void initDatas()    {        for (String title : mTitles)        {            TabFragment tabFragment = new TabFragment();            Bundle args = new Bundle();            args.putString("title", title);            tabFragment.setArguments(args);            mTabs.add(tabFragment);        }        mAdapter = new FragmentPagerAdapter(getSupportFragmentManager())        {            @Override            public int getCount()            {                return mTabs.size();            }            @Override            public Fragment getItem(int arg0)            {                return mTabs.get(arg0);            }        };        initTabIndicator();    }    @Override    public boolean onCreateOptionsMenu(Menu menu)    {        getMenuInflater().inflate(R.menu.main, menu);        return true;    }    private void initTabIndicator()    {        ChangeColorIconWithTextView one = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_one);        ChangeColorIconWithTextView two = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_two);        ChangeColorIconWithTextView three = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_three);        ChangeColorIconWithTextView four = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_four);        mTabIndicator.add(one);        mTabIndicator.add(two);        mTabIndicator.add(three);        mTabIndicator.add(four);        one.setOnClickListener(this);        two.setOnClickListener(this);        three.setOnClickListener(this);        four.setOnClickListener(this);        one.setIconAlpha(1.0f);    }    @Override    public void onPageSelected(int arg0)    {    }    @Override    public void onPageScrolled(int position, float positionOffset,            int positionOffsetPixels)    {        // Log.e("TAG", "position = " + position + " , positionOffset = "        // + positionOffset);        if (positionOffset > 0)        {            ChangeColorIconWithTextView left = mTabIndicator.get(position);            ChangeColorIconWithTextView right = mTabIndicator.get(position + 1);            left.setIconAlpha(1 - positionOffset);            right.setIconAlpha(positionOffset);        }    }    @Override    public void onPageScrollStateChanged(int state)    {    }    @Override    public void onClick(View v)    {        resetOtherTabs();        switch (v.getId())        {        case R.id.id_indicator_one:            mTabIndicator.get(0).setIconAlpha(1.0f);            mViewPager.setCurrentItem(0, false);            break;        case R.id.id_indicator_two:            mTabIndicator.get(1).setIconAlpha(1.0f);            mViewPager.setCurrentItem(1, false);            break;        case R.id.id_indicator_three:            mTabIndicator.get(2).setIconAlpha(1.0f);            mViewPager.setCurrentItem(2, false);            break;        case R.id.id_indicator_four:            mTabIndicator.get(3).setIconAlpha(1.0f);            mViewPager.setCurrentItem(3, false);            break;        }    }    /**     * 重置其他的Tab     */    private void resetOtherTabs()    {        for (int i = 0; i < mTabIndicator.size(); i++)        {            mTabIndicator.get(i).setIconAlpha(0);        }    }    @Override    public boolean onMenuOpened(int featureId, Menu menu)    {        if (featureId == Window.FEATURE_ACTION_BAR && menu != null)        {            if (menu.getClass().getSimpleName().equals("MenuBuilder"))            {                try                {                    Method m = menu.getClass().getDeclaredMethod(                            "setOptionalIconsVisible", Boolean.TYPE);                    m.setAccessible(true);                    m.invoke(menu, true);                } catch (Exception e)                {                }            }        }        return super.onMenuOpened(featureId, menu);    }    private void setOverflowShowingAlways()    {        try        {            // true if a permanent menu key is present, false otherwise.            ViewConfiguration config = ViewConfiguration.get(this);            Field menuKeyField = ViewConfiguration.class                    .getDeclaredField("sHasPermanentMenuKey");            menuKeyField.setAccessible(true);            menuKeyField.setBoolean(config, false);        } catch (Exception e)        {            e.printStackTrace();        }    }}

Activity里面代碼雖然沒什么注釋,但是很簡單哈,就是初始化Fragment,得到我們的適配器,然后設置給ViewPager;

initTabIndicator我們初始化我們的自定義控件,以及加上了點擊事件;

唯一一個需要指出的就是:

我們在onPageScrolled中,動態的獲取position以及positionOffset,然后拿到左右兩個View,設置positionOffset ;

這里表示下慚愧,曾經在高仿微信5.2.1主界面架構 包含消息通知 的onPageScrolled中寫了一堆的if else,在視頻上線后,也有同學立馬就提出了,一行代碼搞定~~

所以,我們這里簡單找了下規律,已經沒有if else的身影了~~~

還剩兩個反射的方法,是控制Actionbar的圖標的,和點擊menu按鍵,將ActionBar的menu顯示在正常區域的~~

3、TabFragment

[java] view plain copy print?
  1. package com.zhy.weixin6.ui;  
  2.   
  3. import android.graphics.Color;  
  4. import android.os.Bundle;  
  5. import android.support.v4.app.Fragment;  
  6. import android.view.Gravity;  
  7. import android.view.LayoutInflater;  
  8. import android.view.View;  
  9. import android.view.ViewGroup;  
  10. import android.widget.TextView;  
  11.   
  12. public class TabFragment extends Fragment  
  13. {  
  14.     private String mTitle = “Default”;  
  15.       
  16.   
  17.     public TabFragment()  
  18.     {  
  19.     }  
  20.   
  21.     @Override  
  22.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  23.             Bundle savedInstanceState)  
  24.     {  
  25.         if (getArguments() != null)  
  26.         {  
  27.             mTitle = getArguments().getString(”title”);  
  28.         }  
  29.   
  30.         TextView textView = new TextView(getActivity());  
  31.         textView.setTextSize(20);  
  32.         textView.setBackgroundColor(Color.parseColor(”#ffffffff”));  
  33.         textView.setGravity(Gravity.CENTER);  
  34.         textView.setText(mTitle);  
  35.         return textView;  
  36.     }  
  37. }  
package com.zhy.weixin6.ui;import android.graphics.Color;import android.os.Bundle;import android.support.v4.app.Fragment;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;public class TabFragment extends Fragment{    private String mTitle = "Default";    public TabFragment()    {    }    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,            Bundle savedInstanceState)    {        if (getArguments() != null)        {            mTitle = getArguments().getString("title");        }        TextView textView = new TextView(getActivity());        textView.setTextSize(20);        textView.setBackgroundColor(Color.parseColor("#ffffffff"));        textView.setGravity(Gravity.CENTER);        textView.setText(mTitle);        return textView;    }}



好了,到此我們的整個案例就結束了~~

大家可以在布局文件中設置各種顏色,4個不同顏色也可以,盡情的玩耍吧~~



源碼點擊下載





建了一個QQ群,方便大家交流。群號:55032675

———————————————————————————————————-

博主部分視頻已經上線,如果你不喜歡枯燥的文本,請猛戳(初錄,期待您的支持):

1、Android 自定義控件實戰 電商活動中的刮刮卡

2、android自定義控件實戰  打造Android流式布局和熱門標簽

3、Android智能機器人“小慕”的實現

4、高仿QQ5.0側滑

5、高仿微信5.2.1主界面及消息提醒









注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com