1. 程式人生 > >自定義View實現微信主頁漸變效果

自定義View實現微信主頁漸變效果

直入主題,先看圖
最終效果圖
下面看實現原理:
1.先是佈局檔案

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </android.support.v4.view.ViewPager> <LinearLayout android:id="@+id/tab_ll"
android:layout_width="match_parent" android:orientation="horizontal" android:layout_height="50dp"> <com.android.tiancb.wxgradient.NavigationItemView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" app:item_icon="@mipmap/ic_launcher"
app:item_text="主頁" app:item_text_size="12sp" /> <com.android.tiancb.wxgradient.NavigationItemView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" app:item_icon="@mipmap/ic_launcher" app:item_text="通訊錄" app:item_text_size="12sp" /> <com.android.tiancb.wxgradient.NavigationItemView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" app:item_icon="@mipmap/ic_launcher" app:item_text="朋友圈" app:item_text_size="12sp" /> <com.android.tiancb.wxgradient.NavigationItemView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" app:item_icon="@mipmap/ic_launcher" app:item_text="我的" app:item_text_size="12sp" app:item_color="#00ff00" /> </LinearLayout> </LinearLayout>

2.自定義屬性檔案

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="navigation_item">
        <attr name="item_icon" format="reference"/>
        <attr name="item_color" format="color"/>
        <attr name="item_text" format="string"/>
        <attr name="item_text_size" format="dimension"/>
    </declare-styleable>
</resources>

3.自定義view

package com.android.tiancb.wxgradient;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by tiancb on 16/1/14.
 */


public class NavigationItemView extends View {
    private String mText;
    private Bitmap mIcon;
    private int mColor = 0xFFff0000;//漸變的顏色
    private int mTextColor = 0x88000000;//字型顏色
    private float mTextSize;
    private Paint mTextPaint;
    private Rect mTextBounds;
    private Rect mIconRect;
    private Rect mTextRect;

    private float itemAlpha;

    public void setItemAlpha(float itemAlpha) {
        this.itemAlpha = itemAlpha;
        invalidate();
    }

    public NavigationItemView(Context context) {
        super(context);
    }

    public NavigationItemView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttrs(context, attrs);
        initPaint();
        initTextRect();
    }

    public NavigationItemView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttrs(context, attrs);
    }


    //初始化自定義屬性
    private void initAttrs(Context context, AttributeSet attrs) {
        try {
            //這是一種方式   另一種是 監聽系統佈局檔案的載入過程————framework層裡面的方式
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.navigation_item);
            mText = typedArray.getString(R.styleable.navigation_item_item_text);
            BitmapDrawable bitmapDrawable = (BitmapDrawable) typedArray.getDrawable(R.styleable.navigation_item_item_icon);
            mIcon = bitmapDrawable.getBitmap();
            mColor = typedArray.getColor(R.styleable.navigation_item_item_color, 0xFFff0000);
            mTextSize = typedArray.getDimension(R.styleable.navigation_item_item_text_size, 10);
            typedArray.recycle();
        }catch (Exception e){
            e.printStackTrace();
        }

    }


    private void initPaint() {
        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(mColor);
        mTextPaint.setTextSize(mTextSize);
    }

    //計算文字所在的位置(也就是我們文字的寬高)
    private void initTextRect() {
        mTextBounds = new Rect();
        mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBounds);
    }
    //計算圖片和文字載螢幕當中所在的區域

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        int bitmapWidth, bitmapHeight;
        bitmapWidth = bitmapHeight = (int) (h * 0.6);
        setIconRect(w, h, bitmapWidth, bitmapHeight);
        setTextRect(w, h, bitmapWidth, bitmapHeight);
    }

    //計算圖片位置的區域
    private void setIconRect(int w, int h, int bitmapWidth, int bitmapHeight) {
        int left = (w - bitmapWidth) / 2;
        int right = left + bitmapWidth;
        int top = (h - bitmapHeight - mTextBounds.height()) / 2;
        int bottom = top + bitmapHeight;
        mIconRect = new Rect(left, top, right, bottom);
    }
    //計算文字位置區域
    private void setTextRect(int w, int h, int bitmapWidth, int bitmapHeight) {
        int textWidth = mTextBounds.width();
        int textHeight = mTextBounds.height();
        int left = (w - textWidth) / 2;
        int right = left + textWidth;
        int top = mIconRect.bottom;
        int bottom = top + textHeight;
        mTextRect = new Rect(left, top, right, bottom);
    }
    //繪製圖片和文字

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 1.清空畫板
        canvasClear(canvas);
        //2.繪製圖片(繪製背景圖片和繪製前景圖片)
        canvasBitmaps(canvas);
        //3.繪製文字(繪製背景文字和繪製前景文字)
        canvasText(canvas);
    }
    private void canvasClear(Canvas canvas){
        canvas.drawBitmap(mIcon,null,mIconRect,null);

//        bgPaint.setTextAlign(Paint.Align.LEFT);
//        //設定畫筆顏色
        mTextPaint.setColor(mTextColor);
        canvas.drawText(mText,getMeasuredWidth() / 2 - mTextBounds.width() / 2, mTextRect.bottom, mTextPaint);
    }
    private void canvasBitmaps(Canvas canvas){
        int alpha = (int) Math.ceil(255 * itemAlpha);
        //二級快取 建立快取圖片(背景圖)
        Bitmap mBgBitmap = Bitmap.createBitmap(getMeasuredWidth(),getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        //快取畫布
        Canvas bgCanvas = new Canvas(mBgBitmap);
        // 建立畫筆
        Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //設定畫筆顏色
        bgPaint.setColor(mColor);
        //防抖動
        bgPaint.setDither(true);
        //設定繪製圖片的透明度
        bgPaint.setAlpha(alpha);
        //繪製背景圖片(繪製背景區域)
        bgCanvas.drawRect(mIconRect,bgPaint);
        //繪製前景圖  設定圖層覆蓋型別
        bgPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        //恢復透明度
        bgPaint.setAlpha(255);
        bgCanvas.drawBitmap(mIcon,null,mIconRect,bgPaint);
        //最後將我們的快取畫布的內容繪製到當前的自定義的View的畫布上面
        canvas.drawBitmap(mBgBitmap,0,0,null);
    }
    //繪製文字
    private void canvasText(Canvas canvas) {
        //文字疊加
        int alpha = (int) Math.ceil(255 * itemAlpha);
        mTextPaint.setColor(mColor);
        mTextPaint.setAlpha(alpha);
//        繪製背景圖片(繪製背景區域)
        canvas.drawText(mText,getMeasuredWidth() / 2 - mTextBounds.width() / 2, mTextRect.bottom, mTextPaint);
    }
}

4.實現介面(主介面)

這裡寫程式碼片package com.android.tiancb.wxgradient;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.widget.LinearLayout;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends FragmentActivity {
    ViewPager viewPager ;
    LinearLayout linearLayout;
    List<TabFragment> fragments;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tab);
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        linearLayout = (LinearLayout) findViewById(R.id.tab_ll);
        fragments = new ArrayList<>();
        List<String> titleList = new ArrayList<>();
        titleList.add("主頁");
        titleList.add("通訊錄");
        titleList.add("朋友圈");
        titleList.add("我的");
        for (String string : titleList){
            TabFragment tabFragment = new TabFragment();
            Bundle bundle = new Bundle();
            bundle.putString("title",string);
            tabFragment.setArguments(bundle);
            fragments.add(tabFragment);
        }
        NavigationAdaper navigationAdaper = new NavigationAdaper(getSupportFragmentManager());
        viewPager.setAdapter(navigationAdaper);
        viewPager.setCurrentItem(0);
        //初始化tab
        NavigationItemView leftView = (NavigationItemView) linearLayout.getChildAt(0);
        leftView.setItemAlpha(1);
//        viewPager.setOnPageChangeListener();用下面的方法代替
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if (positionOffset > 0){
                    NavigationItemView leftView = (NavigationItemView) linearLayout.getChildAt(position);
                    leftView.setItemAlpha(1 - positionOffset);
                    NavigationItemView rightView = (NavigationItemView)linearLayout.getChildAt(position+1);
                    rightView.setItemAlpha(positionOffset);
                }
            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }
    private class NavigationAdaper extends FragmentPagerAdapter {
        public NavigationAdaper(FragmentManager fragmentManager){
            super(fragmentManager);
        };
        @Override
        public Fragment getItem(int position) {

            return fragments.get(position);
        }

        @Override
        public int getCount() {
            return fragments.size();
        }
    }
}

5.另外還有個fragment介面

package com.android.tiancb.wxgradient;


import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * Created by tiancb on 16/1/14.
 */
public class TabFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater,  ViewGroup container,  Bundle savedInstanceState) {
        TextView textView = new TextView(getActivity());
        String title = getArguments().getString("title");
        textView.setText(title);
        textView.setTextSize(50);
        textView.setTextColor(Color.BLACK);
        return textView;
    }
}