Android - 自定义Tab指示器

参考来源:慕课网 http://www.imooc.com/learn/615

1、组合方式实现自定义控件:继承LinearLayout

2、三角形绘制

3、控件滑动 scroll  [Scroller源码分析 http://www.jianshu.com/p/d74f6badb164#]

4、dispatchDraw、onFinishInflate 

 

源代码:

1、MyIndicator

package com.yizhui.indicator.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.yizhui.indicator.R;

import java.util.List;

/**
 * Created by Yizhui on 2016/5/2.
 */
public class MyIndicator extends LinearLayout {

    private int mTriangleWidth;  //三角形宽度
    private int mTriangleHeight; //三角形高度
    private static final float RADIO_TRIANGLE_WIDTH = 1 / 6F;

    private int mInitTranslationX;
    private int mTranslationX;

    private Path mPath;
    private Paint mPaint;

    private int mTabVisibleCount;  //可见Tab个数
    private static final int COUNT_DEFAULT_TAB = 4; //默认可见Tab个数


    private static final int COLOR_TAB_NORMAL=Color.BLUE;
    private static final int COLOR_TAB_HIGHLIGHT=Color.RED;

    private ViewPager mViewPager;

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

    public MyIndicator(Context context, AttributeSet attrs) {
        super(context, attrs);

        //获取可见Tab个数
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyIndicator);
        mTabVisibleCount = a.getInteger(R.styleable.MyIndicator_visible_tab_count, COUNT_DEFAULT_TAB);
        if (mTabVisibleCount < 0) {
            mTabVisibleCount = COUNT_DEFAULT_TAB;
        }
        a.recycle();

        //初始化画笔
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.WHITE);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setPathEffect(new CornerPathEffect(3));
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        //绘制三角形
        canvas.save();
        canvas.translate(mInitTranslationX + mTranslationX, getHeight() + 2);
        canvas.drawPath(mPath, mPaint);
        canvas.restore();

        super.dispatchDraw(canvas);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

//        int childCount = getChildCount();
//        if (childCount == 0) return;
//
//        int screenWidth = getScreenWidth();
//        for (int i = 0; i < childCount; i++) {
//            View view = getChildAt(i);
//            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) view.getLayoutParams();
//            lp.weight = 0;
//            lp.width = screenWidth / mTabVisibleCount;
//            view.setLayoutParams(lp);
//        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    //获取屏幕宽度
    private int getScreenWidth() {
        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics disPlayMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(disPlayMetrics);
        return disPlayMetrics.widthPixels;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        mTriangleWidth = (int) (w / Math.max(mTabVisibleCount,COUNT_DEFAULT_TAB) * RADIO_TRIANGLE_WIDTH);
        mTriangleHeight = mTriangleWidth / 2;
        mInitTranslationX = w / mTabVisibleCount / 2 - mTriangleWidth / 2;

        initTriangle();
    }

    private void initTriangle() {
        mPath = new Path();
        mPath.moveTo(0, 0);
        mPath.lineTo(mTriangleWidth, 0);
        mPath.lineTo(mTriangleWidth / 2, -mTriangleHeight);
        mPath.close();
    }

    public void scroll(int position, float positionOffset) {
        int tabWidth = getWidth() / mTabVisibleCount;
        mTranslationX = (int) (tabWidth * (position + positionOffset));

        if (position + 1 >= mTabVisibleCount && positionOffset > 0 && getChildCount() > mTabVisibleCount) {
            scrollTo((int) (tabWidth * (position + 1 - mTabVisibleCount + positionOffset)), 0);
        }

        invalidate();
    }

    public void setTabVisibleCount(int count){
        mTabVisibleCount=count;
    }

    public void setTabItemTitles(List<String> titles){
        if(titles!=null && titles.size()>0){
            removeAllViews();
            for(String title:titles){
                addView(generateTabItem(title));
            }
        }
    }

    private TextView generateTabItem(String title){
        TextView tv=new TextView(getContext());
        LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
        lp.width=getScreenWidth()/mTabVisibleCount;
        tv.setGravity(Gravity.CENTER);
        //tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
        tv.setTextColor(COLOR_TAB_NORMAL);
        tv.setLayoutParams(lp);
        tv.setText(title);
        return tv;
    }


    //高亮Tab文本
    private void setTabTextHighline(int position){
        for(int i=0;i<getChildCount();i++){
            ((TextView)getChildAt(i)).setTextColor(COLOR_TAB_NORMAL);
        }
        ((TextView)getChildAt(position)).setTextColor(COLOR_TAB_HIGHLIGHT);
    }

    public interface OnPageChangeListener{
         void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
         void onPageSelected(int position);
         void onPageScrollStateChanged(int state);
    }

    private OnPageChangeListener onPageChangeListener;
    public void setOnPageChangeListener(OnPageChangeListener listener){
        onPageChangeListener=listener;
    }

    public void setViewPager(ViewPager viewPager){
        mViewPager=viewPager;

        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                scroll(position,positionOffset);
                setTabTextHighline(position);

                if(onPageChangeListener!=null)
                    onPageChangeListener.onPageScrolled(position,positionOffset,positionOffsetPixels);
            }

            @Override
            public void onPageSelected(int position) {
                if(onPageChangeListener!=null)
                    onPageChangeListener.onPageSelected(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                if(onPageChangeListener!=null)
                    onPageChangeListener.onPageScrollStateChanged(state);
            }
        });
    }
}

2、attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="visible_tab_count" format="integer"></attr>
    <declare-styleable name="MyIndicator">
        <attr name="visible_tab_count"></attr>
    </declare-styleable>
    
</resources>

3、activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:cyz="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context="com.yizhui.indicator.MainActivity"
    android:orientation="vertical">

    <com.yizhui.indicator.view.MyIndicator
        android:id="@+id/myIndicator"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:orientation="horizontal"
        android:background="#3333"
        cyz:visible_tab_count="1">

        <!--<TextView-->
            <!--android:layout_width="0dp"-->
            <!--android:layout_height="match_parent"-->
            <!--android:layout_weight="1"-->
            <!--android:gravity="center"-->
            <!--android:text="AAA"/>-->
        <!--<TextView-->
            <!--android:layout_width="0dp"-->
            <!--android:layout_height="match_parent"-->
            <!--android:layout_weight="1"-->
            <!--android:gravity="center"-->
            <!--android:text="BBB"/>-->
        <!--<TextView-->
            <!--android:layout_width="0dp"-->
            <!--android:layout_height="match_parent"-->
            <!--android:layout_weight="1"-->
            <!--android:gravity="center"-->
            <!--android:text="CCC"/>-->

    </com.yizhui.indicator.view.MyIndicator>

<android.support.v4.view.ViewPager
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"></android.support.v4.view.ViewPager>
</LinearLayout>

4、MainActivity

package com.yizhui.indicator;

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.view.Window;
import android.widget.Toast;

import com.yizhui.indicator.view.MyIndicator;

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

public class MainActivity extends FragmentActivity {

    private ViewPager mViewPager;
    private MyIndicator mMyIndicator;

    private List<String> mTitles=Arrays.asList("AAA","BBB","CCC","DDD","EEE","FFF","GGG","HHH");
    private List<SimpleFragment> mContents=new ArrayList<SimpleFragment>();
    private FragmentPagerAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);

        initViews();
        initDatas();
    }

    private void initViews() {
        mViewPager=(ViewPager)findViewById(R.id.viewPager);
        mMyIndicator=(MyIndicator)findViewById(R.id.myIndicator);
    }

    private void initDatas(){
        for(String title:mTitles){
            mContents.add(SimpleFragment.newInstance(title));
        }

        mAdapter=new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public Fragment getItem(int position) {
                return mContents.get(position);
            }

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

        mViewPager.setAdapter(mAdapter);

        mMyIndicator.setTabVisibleCount(3);
        mMyIndicator.setTabItemTitles(mTitles);
        mMyIndicator.setViewPager(mViewPager);

        mMyIndicator.setOnPageChangeListener(new MyIndicator.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                Toast.makeText(MainActivity.this, "position " + (position + 1), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }
}

5、SimpleFragment

package com.yizhui.indicator;

import android.os.Bundle;
import android.support.annotation.Nullable;
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;

/**
 * Created by Yizhui on 2016/5/2.
 */
public class SimpleFragment extends Fragment {

    private String mTitle;
    public static final String BUNDLE_TITLE="title";

    public static SimpleFragment newInstance(String title){
        Bundle bundle=new Bundle();
        bundle.putString(BUNDLE_TITLE,title);
        SimpleFragment fragment=new SimpleFragment();
        fragment.setArguments(bundle);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        Bundle bundle=getArguments();
        if(bundle!=null){
            mTitle=bundle.getString(BUNDLE_TITLE);
        }

        TextView tv=new TextView(getActivity());
        tv.setText(mTitle);
        tv.setGravity(Gravity.CENTER);

        return tv;
    }
}

  

posted @ 2016-05-03 11:35  chenyizh  阅读(316)  评论(0)    收藏  举报