Android自定义横条指示器,【Android】顶部Tab指示器(自定义LinearLayout+Viewpager)

2016-11-13 第一篇 ViewPagerIndicator

根据鸿洋的视频编写,然后自己添加了可以滑动的图形方式,直线或者三角形。还添加了可以在xml中自定义样式的功能。

最后效果演示图

AAffA0nNPuCLAAAAAElFTkSuQmCC

AAffA0nNPuCLAAAAAElFTkSuQmCC

ChangeablePagerIndicator类(顶部的指示器类)

重写父类主要的方法:

1.dispatchDraw(Canvas canvas) 绘制直线或者三角形

AAffA0nNPuCLAAAAAElFTkSuQmCC

2.onFinishInflate() xml文件加载完成之后调用此放过,在xml中设置item时,在此方法重新设置item的宽度

AAffA0nNPuCLAAAAAElFTkSuQmCC

Tab item移动的方法:

1.scroll(int position,float offset)

AAffA0nNPuCLAAAAAElFTkSuQmCC

代码生成Items的方法

1.setTabItems(List titles)

AAffA0nNPuCLAAAAAElFTkSuQmCC

内部处理ViewPager的滑动

1.设置ViewPager :setViewPager(ViewPager viewPager,int currentPos)

AAffA0nNPuCLAAAAAElFTkSuQmCC

2.设置监听事件(这里的IndicatorListener是实现ViewPager.OnPageChangeListener接口)

AAffA0nNPuCLAAAAAElFTkSuQmCC

点击Item跳转ViewPager

1.setItemClickListener()

AAffA0nNPuCLAAAAAElFTkSuQmCC

xml中自定义的属性值

AAffA0nNPuCLAAAAAElFTkSuQmCC

AAffA0nNPuCLAAAAAElFTkSuQmCC

全部代码

指示器类代码(ChangeablePagerIndicator.java)

package jfsl.view.toptab.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.util.TypedValue;

import android.view.Gravity;

import android.view.View;

import android.view.WindowManager;

import android.widget.LinearLayout;

import android.widget.TextView;

import java.util.List;

import jfsl.view.toptab.R;

import jfsl.view.toptab.listener.IndicatorListener;

/**

* 顶部Tab的导航区域

* 固定的顶部Indicator

*

* @version 1.0

* @aduthor JFSL

* @date 2016/11/12

* @date 2016-11-13 15:08 完成

*/

public class ChangeablePagerIndicator extends LinearLayout

{

//默认的高亮文本颜色:白色

public static final int COLOR_TEXT_HIGHLIGHT = Color.parseColor("#FFFFFFFF");

//默认的正常文本颜色:灰色

public static final int COLOR_TEXT_NORMAL = Color.parseColor("#77FFFFFF");

//默认绘制图形的颜色:白色

public static final int COLOR_GRAPHICS = Color.parseColor("#FFFFFFFF");

//默认Tab的文本大小 16sp

public static final int TAB_TEXT_SIZE = 16;

//直线的高度 10dp

public static final int LINE_HEIGHT = 10;

//最小的显示Tab的数量

public static final int DEFAULT_VISIBLE_COUNTS = 3;

//绘制的类型:1.直线 2.三角形

public static final int STYLE_LINE = 100;

public static final int STYLE_TRIANGLE = 200;

//三角形的比例

public static final float TRIANGLE_RADIO = 1 / 6F;

//绘制三角形的画笔

private Paint mTrianglePaint;

//绘制三角形的路径

private Path mTrianglePath;

//三角形的宽

private int mTriangleWidth;

//三角形的高

private int mTriangleHeight;

//绘制直线的画笔

private Paint mLinePaint;

//线的宽度

private int mLineWidth;

//初始位置时三角形的位置

private int mStartX;

//移动时三角形的位置

private int mMoveX;

//绘制的类型

private int mDrawStyle = STYLE_LINE;

//默认显示的tab item数量

private int mDefaultVisibleCounts;

//高亮文本的颜色

private int mHighLightColor;

//普通文本的颜色

private int mNormalTextColor;

//文本大小

private int mTextSize;

//线的高度(strokeWidth)

private int mLineHeight;

//直线或者三角形的颜色

private int mGraphicsColor;

public ChangeablePagerIndicator(Context context)

{

this(context,null);

}

public ChangeablePagerIndicator(Context context,AttributeSet attrs)

{

super(context,attrs);

//获取自定义的值

getCustomValue(context,attrs);

//初始化三角形的画笔

initTrianglePaint();

//初始化直线的画笔

initLinePaint();

}

/**

* 加载完XML时,调用此方法

*/

@Override

protected void onFinishInflate()

{

super.onFinishInflate();

int coutns = getChildCount();

if(coutns == 0)

return;

for(int i = 0;i < coutns;i++)

{

View view = getChildAt(i);

LinearLayout.LayoutParams params = (LayoutParams)view.getLayoutParams();

params.weight = 0;

params.width = getScreenWidth() / mDefaultVisibleCounts;

view.setLayoutParams(params);

}

//设置监听

setItemClickListener();

//直线的宽度

mLineWidth = getScreenWidth() / mDefaultVisibleCounts;

}

@Override

protected void onSizeChanged(int width,int height,int oldWidth,int oldHeight)

{

super.onSizeChanged(width,height,oldWidth,oldHeight);

//创建三角形

createIndicatorTriangle();

}

@Override

protected void dispatchDraw(Canvas canvas)

{

canvas.save();

if(mDrawStyle == STYLE_LINE)

{

//绘制直线

canvas.drawLine(mMoveX,getHeight(),mMoveX + mLineWidth,getHeight(),mLinePaint);

}

if(mDrawStyle == STYLE_TRIANGLE)

{

//绘制三角形

canvas.translate(mStartX + mMoveX,getHeight());

canvas.drawPath(mTrianglePath,mTrianglePaint);

}

canvas.restore();

super.dispatchDraw(canvas);

}

/**

* 获取自定义的值

*

* @param attrs

*/

private void getCustomValue(Context context,AttributeSet attrs)

{

TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.ChangeablePagerIndicator);

//获取默认显示的可见Tab的数量

mDefaultVisibleCounts = attributes.

getInt(R.styleable.ChangeablePagerIndicator_default_display_counts,DEFAULT_VISIBLE_COUNTS);

mDefaultVisibleCounts = Math.max(DEFAULT_VISIBLE_COUNTS,mDefaultVisibleCounts);

//高亮文本的颜色

mHighLightColor = attributes.getColor(R.styleable.ChangeablePagerIndicator_high_light_color,COLOR_TEXT_HIGHLIGHT);

//普通文本的颜色

mNormalTextColor = attributes.getColor(R.styleable.ChangeablePagerIndicator_normal_text_color,COLOR_TEXT_NORMAL);

//文本大小

mTextSize = attributes.getInt(R.styleable.ChangeablePagerIndicator_text_size,TAB_TEXT_SIZE);

//线的高度(strokeWidth)

mLineHeight = attributes.getInt(R.styleable.ChangeablePagerIndicator_graphics_height,LINE_HEIGHT);

//直线或者三角形的颜色

mGraphicsColor = attributes.getColor(R.styleable.ChangeablePagerIndicator_graphics_color,COLOR_GRAPHICS);

//绘制的类型

boolean drawStyle = attributes.getBoolean(R.styleable.ChangeablePagerIndicator_is_draw_line,true);

mDrawStyle = drawStyle ? STYLE_LINE : STYLE_TRIANGLE;

//直线的宽度

mLineWidth = getScreenWidth() / mDefaultVisibleCounts;

attributes.recycle();

}

/**

* 初始化三角形的画笔

*/

private void initTrianglePaint()

{

mTrianglePaint = new Paint();

mTrianglePaint.setAntiAlias(true);

//三角形的画笔颜色

mTrianglePaint.setColor(mGraphicsColor);

mTrianglePaint.setStyle(Paint.Style.FILL);

//绘制角时的弧度

mTrianglePaint.setPathEffect(new CornerPathEffect(2));

}

/**

* 初始化直线的画笔

*/

private void initLinePaint()

{

mLinePaint = new Paint(mTrianglePaint);

mLinePaint.setStrokeWidth(mLineHeight);

}

/**

* 创建指示器的三角形

*/

private void createIndicatorTriangle()

{

int tabWidth = getScreenWidth() / mDefaultVisibleCounts;

//三角形的宽度

mTriangleWidth = (int)(tabWidth * TRIANGLE_RADIO);

//初始位置时三角形的位置

mStartX = (tabWidth - mTriangleWidth) / 2;

//三角形的高度

mTriangleHeight = mTriangleWidth / 3;

//绘制三三角形路径

mTrianglePath = new Path();

mTrianglePath.moveTo(0,0);

mTrianglePath.lineTo(mTriangleWidth,0);

mTrianglePath.lineTo(mTriangleWidth / 2,- mTriangleHeight);

mTrianglePath.close();

}

/**

* 水平滚动

*

* @param position

* @param offset

*/

public void scroll(int position,float offset)

{

int tabWidth = getWidth() / mDefaultVisibleCounts;

//指示器移动的距离

mMoveX = (int)(tabWidth * (position + offset));

//移动Tab

if(position >= (mDefaultVisibleCounts - 2) && offset > 0

&& getChildCount() > mDefaultVisibleCounts

&& position != getChildCount() - 2)

{

if(mDefaultVisibleCounts != 1)

{

int scrollX = (position - (mDefaultVisibleCounts - 2)) * tabWidth

+ (int)(tabWidth * offset);

this.scrollTo(scrollX,0);

} else

{

this.scrollTo((position * tabWidth

+ (int)(tabWidth * offset)),0);

}

}

//重新绘制

invalidate();

}

/**

* 设置绘制的类型

* 1.STYLE_LINE 直线

* 2.STYLE_TRIANGLE 三角形

*/

public void setDrawStyle(int style)

{

mDrawStyle = style;

invalidate();

}

public void setDefaultVisibleCounts(int counts)

{

mDefaultVisibleCounts = counts;

if(counts < DEFAULT_VISIBLE_COUNTS)

mDefaultVisibleCounts = DEFAULT_VISIBLE_COUNTS;

//直线的宽度

mLineWidth = getScreenWidth() / mDefaultVisibleCounts;

}

/**

* 不用加载布局文件,代码生成

*

* @param titles

*/

public void setTabItems(List titles)

{

if(titles == null)

return;

//首先移除所有的View

this.removeAllViews();

//根据标题生成TextView

for(String title : titles)

{

this.addView(generateTitleView(title));

}

//设置监听

setItemClickListener();

}

/**

* 设置ViewPager

*

* @param viewPager

* @param currentPos 当前选的位置

*/

private ViewPager mViewPager;

public void setViewPager(ViewPager viewPager,int currentPos)

{

mViewPager = viewPager;

viewPager.addOnPageChangeListener(mListener);

//设置当前选中项

viewPager.setCurrentItem(currentPos);

}

/**

* ViewPager监听

*/

private IndicatorListener mListener = new IndicatorListener()

{

@Override

public void scrollChanged(int position,float offset)

{

//进行Tab滚动

scroll(position,offset);

}

@Override

public void selected(int position)

{

//设置高亮文本,当前ViewPager与Tab一一对应

setHighLightText(position);

}

};

/**

* Tab Item的点击监听

*/

private void setItemClickListener()

{

for(int i = 0;i < getChildCount();i++)

{

//点击的位置

final int clickPosition = i;

View view = getChildAt(i);

if(view instanceof TextView)

{

view.setOnClickListener(new OnClickListener()

{

@Override

public void onClick(View view)

{

//ViewPager跳到对应的选中项

mViewPager.setCurrentItem(clickPosition);

}

});

}

}

}

/**

* 根据标题生成TextView

*

* @param title

* @return

*/

private View generateTitleView(String title)

{

TextView tv = new TextView(getContext());

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);

params.width = getScreenWidth() / mDefaultVisibleCounts;

tv.setGravity(Gravity.CENTER);

tv.setText(title);

tv.setTextSize(TypedValue.COMPLEX_UNIT_SP,mTextSize);

tv.setTextColor(mNormalTextColor);

tv.setLayoutParams(params);

return tv;

}

/**

* 设置高亮显示的文本

* 也就是当前选中的文本

*

* @param position

*/

private void setHighLightText(int position)

{

for(int i = 0;i < getChildCount();i++)

{

View view = getChildAt(i);

if(view instanceof TextView)

{

//高亮颜色

if(i == position)

((TextView)view).setTextColor(mHighLightColor);

//正常颜色

else

((TextView)view).setTextColor(mNormalTextColor);

}

}

}

/**

* 获取屏幕的宽度

*

* @return

*/

private int getScreenWidth()

{

WindowManager manager = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);

DisplayMetrics metrics = new DisplayMetrics();

manager.getDefaultDisplay().getMetrics(metrics);

return metrics.widthPixels;

}

}

自定义ViewPager监听类(IndicatorListener.java)

package jfsl.view.toptab.listener;

import android.support.v4.view.ViewPager;

/**

* @version 1.0

* @aduthor JFSL

* @date 2016/11/13 0013

*/

public abstract class IndicatorListener implements ViewPager.OnPageChangeListener

{

@Override

public void onPageScrolled(int position,float positionOffset,int positionOffsetPixels)

{

scrollChanged(position,positionOffset);

}

@Override

public void onPageSelected(int position)

{

selected(position);

}

@Override

public void onPageScrollStateChanged(int state)

{

}

/**

* ViewPager滑动

* @param position

* @param offset

*/

public abstract void scrollChanged(int position,float offset);

/**

* 选择当前页

* @param position

*/

public abstract void selected(int position);

}

ViewPager指示器类(TopViewPagerAdapter.java)

package jfsl.view.toptab.adapter;

import android.content.Context;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentManager;

import android.support.v4.app.FragmentPagerAdapter;

import java.util.List;

import jfsl.view.toptab.fragment.SimpleFragment;

/**

* @version 1.0

* @aduthor JFSL

* @date 2016/11/12 0012

*/

public class TopViewPagerAdapter extends FragmentPagerAdapter

{

private Context mContext;

private List mFragments;

public TopViewPagerAdapter(FragmentManager fm,Context context,List fragments)

{

super(fm);

mContext = context;

mFragments = fragments;

}

@Override

public Fragment getItem(int position)

{

return mFragments.get(position);

}

@Override

public int getCount()

{

return mFragments.size();

}

}

测试用的Fragment(SimpleFragment.java)

package jfsl.view.toptab.fragment;

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;

/**测试用的Fragment

* @version 1.0

* @aduthor JFSL

* @date 2016/11/12 0012

*/

public class SimpleFragment extends Fragment

{

public static final String BUNDLE_TITLE = "title";

private String mTitle;

@Nullable

@Override

public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState)

{

Bundle bundle = getArguments();

if(bundle != null)

mTitle = bundle.getString(BUNDLE_TITLE);

TextView textView = new TextView(getActivity());

textView.setText(mTitle);

textView.setGravity(Gravity.CENTER);

return textView;

}

/**

* 获取实例

* @param title

* @return

*/

public static SimpleFragment newInstance(String title)

{

Bundle bundle = new Bundle();

bundle.putString(BUNDLE_TITLE,title);

SimpleFragment fragment = new SimpleFragment();

fragment.setArguments(bundle);

return fragment;

}

}

测试的Activity(ChangeableMainActivity .java)

package jfsl.view.toptab;

import android.os.Bundle;

import android.support.v4.app.FragmentPagerAdapter;

import android.support.v4.view.ViewPager;

import android.support.v7.app.AppCompatActivity;

import android.view.Window;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

import jfsl.view.toptab.adapter.TopViewPagerAdapter;

import jfsl.view.toptab.fragment.SimpleFragment;

import jfsl.view.toptab.view.ChangeablePagerIndicator;

/**

* 测试自定义View的效果

*/

public class ChangeableMainActivity extends AppCompatActivity

{

private ViewPager mViewPager;

private ChangeablePagerIndicator mIndicator;

private List mTitles = Arrays.asList("国际","军事","社会","娱乐","体育","财经","历史","本地","中国");

private List mFragments = new ArrayList<>();

private FragmentPagerAdapter mPagerAdapter;

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.activity_main_changeable2);

initViews();

initDatas();

initEvent();

}

private void initEvent()

{

}

private void initDatas()

{

for(String title : mTitles)

{

mFragments.add(SimpleFragment.newInstance(title));

}

mPagerAdapter = new TopViewPagerAdapter(getSupportFragmentManager(),this,mFragments);

mViewPager.setAdapter(mPagerAdapter);

// mIndicator.setDefaultVisibleCounts(3);

//设置绘制的类型

// mIndicator.setDrawStyle(ChangeablePagerIndicator.STYLE_TRIANGLE);

//注意:其他设置要放在这个之前

mIndicator.setTabItems(mTitles);

mIndicator.setViewPager(mViewPager,1);

}

private void initViews()

{

mIndicator = (ChangeablePagerIndicator)findViewById(R.id.id_pager_indicator);

mViewPager = (ViewPager)findViewById(R.id.id_viewpager);

}

}

自定义属性文件(indicator_attrs.xml)

颜色值文件(colors.xml)

#009688

#06776d

#FF4081

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值