Indicator确实是个老梗了...
有重写HorizontalScrollView的,有重写LinearLayout。
这个是重写LinearLayout的哦,往LinearLayout里add TextView用作tab标签,在LinearLayout底部画一个矩形当作指示器。
ViewPager滚动的时候用简单的小学加减乘除混合运算来机选这个矩形位置,然后滚动就好了
属性
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <attr name="tab_color_normal" format="color" />
- <attr name="tab_color_light" format="color" />
- <attr name="cursor_color" format="color" />
- <attr name="cursor_height" format="dimension" />
- <declare-styleable name="Indicator">
- <attr name="tab_color_normal" />
- <attr name="tab_color_light" />
- <attr name="cursor_color" />
- <attr name="cursor_height" />
- </declare-styleable>
- </resources>
Indicator.java 关键的地方都谢了注释
- package com.mingwei.indicator.view;
- import java.util.List;
- import android.annotation.TargetApi;
- import android.content.Context;
- import android.content.res.TypedArray;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Paint.Style;
- import android.graphics.Rect;
- import android.os.Build;
- import android.support.v4.view.ViewPager;
- import android.support.v4.view.ViewPager.OnPageChangeListener;
- import android.util.AttributeSet;
- import android.util.TypedValue;
- import android.view.Gravity;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.HorizontalScrollView;
- import android.widget.LinearLayout;
- import android.widget.TextView;
- import com.mingwei.indicator.R;
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- public class Indicator extends LinearLayout implements OnClickListener, OnPageChangeListener {
- /**
- * 绘制时用的画笔
- */
- private Paint mPaint;
- /**
- * 默认颜色
- */
- private int mCursorColor;
- /**
- * 滚动的指示器的矩形范围
- */
- private Rect mRect = new Rect();
- /**
- * 滚动游标的绘制范围
- */
- private int mL, mR, mT, mB;
- /**
- * 最多可见的游标数
- */
- private int mVisiableTabCount = 4;
- /**
- * 游标高度
- */
- private int mCursorHeight = 6;
- /**
- * tab的宽度
- */
- private int mTabWidth;
- /**
- * 选中和非选中状态的标签文字颜色
- */
- private int mTabColorNormal;
- private int mTabColorLight;
- /**
- * 水平滚动的距离
- */
- private float mTranslationX;
- /**
- * 需要监听ViewPager动作来跟新游标
- */
- private ViewPager mViewPager;
- public Indicator(Context context) {
- this(context, null);
- }
- public Indicator(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
- public Indicator(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- initAttr(context, attrs, defStyleAttr);
- mPaint = new Paint();
- mPaint.setColor(mCursorColor);
- mPaint.setAntiAlias(true);
- mPaint.setStyle(Style.FILL);
- }
- private void initAttr(Context context, AttributeSet attrs, int defStyleAttr) {
- TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.Indicator);
- mTabColorNormal = array.getColor(R.styleable.Indicator_tab_color_normal, Color.BLACK);
- mTabColorLight = array.getColor(R.styleable.Indicator_tab_color_light, Color.WHITE);
- mCursorColor = array.getColor(R.styleable.Indicator_cursor_color, Color.BLACK);
- mCursorHeight = array.getDimensionPixelSize(R.styleable.Indicator_cursor_height, mCursorHeight);
- array.recycle();
- }
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- }
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- int count = getChildCount();
- if (count == 0) {
- return;
- }
- mTabWidth = getWidth() / mVisiableTabCount;
- for (int i = 0; i < count; i++) {
- View view = getChildAt(i);
- LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
- params.weight = 0;
- params.width = mTabWidth;
- params.height = getHeight() - mCursorHeight;
- view.setLayoutParams(params);
- }
- mL = 0;
- mT = getHeight() - mCursorHeight;
- mR = mTabWidth;
- mB = getHeight();
- mRect = new Rect(mL, mT, mR, mB);
- }
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
- canvas.save();
- canvas.translate(mTranslationX, 0);
- canvas.drawRect(mRect, mPaint);
- canvas.restore();
- }
- private void scroll(int position, float offset) {
- mTranslationX = getWidth() / mVisiableTabCount * (position + offset);
- /**
- * 当tab数大于可见数目的时候,整个容器滚动
- */
- if (getChildCount() > mVisiableTabCount && offset > 0 && (position >= mVisiableTabCount - 2)) {
- if (mVisiableTabCount != 1) {
- /**
- * 当tab等于可见数目不是倒数第二个时滚动容器,否则仍然滚动游标
- */
- if (position != getChildCount() - 2) {
- scrollTo((position - (mVisiableTabCount - 2)) * mTabWidth + (int) (offset * mTabWidth), 0);
- }
- } else {
- scrollTo(position * mTabWidth + (int) (offset * mTabWidth), 0);
- }
- }
- invalidate();
- }
- public void setViewPager(ViewPager viewPager) {
- mViewPager = viewPager;
- mViewPager.setOnPageChangeListener(this);
- }
- public void setTabs(String[] tabs) {
- removeAllViews();
- for (String t : tabs) {
- createChild(t);
- }
- TextView view = (TextView) getChildAt(0);
- view.setTextColor(mTabColorLight);
- }
- public void setTabs(List<String> tabs) {
- removeAllViews();
- for (String t : tabs) {
- createChild(t);
- }
- TextView view = (TextView) getChildAt(0);
- view.setTextColor(mTabColorLight);
- }
- private void setTabLight(int arg0) {
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- TextView view = (TextView) getChildAt(i);
- if (i == arg0) {
- view.setTextColor(mTabColorLight);
- } else {
- view.setTextColor(mTabColorNormal);
- }
- }
- }
- /**
- * 创建子View
- *
- * @param text
- */
- private void createChild(String text) {
- TextView view = new TextView(getContext());
- view.setText(text);
- view.setGravity(Gravity.CENTER);
- view.setTextColor(mTabColorNormal);
- view.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
- view.setOnClickListener(this);
- view.setTag(getChildCount());
- addView(view);
- }
- @Override
- public void onPageScrollStateChanged(int arg0) {
- }
- @Override
- public void onPageScrolled(int arg0, float arg1, int arg2) {
- scroll(arg0, arg1);
- }
- @Override
- public void onPageSelected(int arg0) {
- setTabLight(arg0);
- }
- @Override
- public void onClick(View arg0) {
- int i = (Integer) arg0.getTag();
- mViewPager.setCurrentItem(i);
- }
- }
XML使用
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <com.mingwei.indicator.view.Indicator
- xmlns:ming="http://schemas.android.com/apk/res-auto"
- android:id="@+id/indicator"
- android:layout_width="match_parent"
- android:layout_height="45dp"
- android:orientation="horizontal"
- ming:cursor_color="@color/indicator_color"
- ming:cursor_height="3dp"
- ming:tab_color_light="@color/tab_color_checked"
- ming:tab_color_normal="@color/tab_color_normal" >
- </com.mingwei.indicator.view.Indicator>
- <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>
- package com.mingwei.indicator;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- 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.Menu;
- import android.view.MenuItem;
- import com.mingwei.indicator.view.Indicator;
- public class MainActivity extends FragmentActivity {
- private ViewPager mViewPager;
- private List<Fragment> mFragments = new ArrayList<Fragment>();
- private FragmentPagerAdapter mAdapter;
- private List<String> mStrings = Arrays.asList("标签1", "标签2", "标签3", "标签4", "标签5");
- private Indicator mIndicator;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initView();
- }
- private void initView() {
- for (String tabs : mStrings) {
- SimpleFragment fragment = SimpleFragment.newInstance(tabs);
- mFragments.add(fragment);
- }
- mViewPager = (ViewPager) findViewById(R.id.viewpager);
- mIndicator = (Indicator) findViewById(R.id.indicator);
- mIndicator.setTabs(mStrings);
- mIndicator.setViewPager(mViewPager);
- mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
- @Override
- public int getCount() {
- return mFragments.size();
- }
- @Override
- public Fragment getItem(int position) {
- return mFragments.get(position);
- }
- };
- mViewPager.setAdapter(mAdapter);
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
- if (id == R.id.action_settings) {
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
- }