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;
}
}
浙公网安备 33010602011771号