mList = getContext().getResources().getStringArray(array.getResourceId(R.styleable.Indicator_array, 0));
mTextNomal = array.getInteger(R.styleable.Indicator_text_nomal_size, 12);
mTextPress = array.getInteger(R.styleable.Indicator_text_press_size, 13);
mText_Nomal = array.getColor(R.styleable.Indicator_text_nomal_color, Color.GRAY);
mText_Press = array.getColor(R.styleable.Indicator_text_press_color, Color.BLACK);
mSelected = array.getInteger(R.styleable.Indicator_selected, 0);
isFull = array.getBoolean(R.styleable.Indicator_isFull, false);
mAnimationTime = array.getInteger(R.styleable.Indicator_speed, 300);
mBai = array.getFloat(R.styleable.Indicator_multiply, (float) 1.2);
mHeight = array.getInteger(R.styleable.Indicator_line_hegith, 5);
for (int i = 0; i < mList.length; i++) {
mListTitle.add(mList[i]);
}
array.recycle();
}
- onLayout初始化布局
添加控件
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (!mIsCheck) {
mIsCheck = true;
initView();
}
}
添加textview以及线
/**
- 初始化布局
*/
private void initView() {
measure(0, 0);
//获取每个textview布局所占的宽度
mContWidth = getWidth() / mListTitle.size();
//添加线
mLine = new View(getContext());
addView(mLine);
int mWeight;
if (isFull) {
mWeight = mContWidth;
} else {
mWeight = (int) (setLineLength(mListTitle.get(mSelected)) * mBai);
if (mWeight > mContWidth) {
mWeight = mContWidth;
}
}
//设置线的基本属性
LayoutParams mLayoutParams1 = new LayoutParams(mWeight, mHeight);
mLayoutParams1.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
mLine.setLayoutParams(mLayoutParams1);
mLine.setBackgroundColor(mColor);
//获取上一次所在位置
mEndAddress = mContWidth * mSelected + (mContWidth - mWeight) / 2;
//添加textview
for (int i = 0; i < mListTitle.size(); i++) {
addTextView(i);
}
//初始化点击事件
setListener();
}
/**
- 添加textview
*/
private void addTextView(int i) {
//初始化textview
TextView textView = new TextView(getContext());
textView.setText(mListTitle.get(i));
//设置textview基本属性
LayoutParams mLayoutParams = new LayoutParams(mContWidth, LayoutParams.MATCH_PARENT);
mLayoutParams.leftMargin = mContWidth * i;
mLayoutParams.addRule(CENTER_VERTICAL);
textView.setLayoutParams(mLayoutParams);
textView.setGravity(Gravity.CENTER);
if (i == mSelected) {
textView.setTextColor(mText_Press);
textView.setTextSize(mTextPress);
} else {
textView.setTextColor(mText_Nomal);
textView.setTextSize(mTextNomal);
}
//添加textview到布局
mTextList.add(textView);
addView(textView);
}
- 动画
动画就简单了直接一个移动动画就好了
/**
-
动画
-
@param statX 开始位置
-
@param endX 结束位置
*/
private void setAnimation(int statX, int endX) {
AnimationSet mSet = new AnimationSet(true);
TranslateAnimation translate1 = new TranslateAnimation(
statX, endX, 0, 0);
mSet.addAnimation(translate1);
mSet.setFillAfter(true);
mSet.setDuration(mAnimationTime);
mLine.startAnimation(mSet);
}
- 修改下标位置
计算修改下标的位置
/**
-
改变下标
-
@param position
*/
public void setChanger(int position) {
//改为默认字体颜色修改选中字体颜色
resetColor();
mTextList.get(position).setTextColor(mText_Press);
mTextList.get(position).setTextSize(mTextPress);
mSelected = position;
int mWeight;
if (isFull) {
mWeight = mContWidth;
} else {
mWeight = (int) (setLineLength(mListTitle.get(mSelected)) * mBai);
if (mWeight > mContWidth) {
mWeight = mContWidth;
}
}
/**
- 计算当前选择textview的X点位置
*/
int way = mContWidth * mSelected + (mContWidth - mWeight) / 2;
LayoutParams mLayoutParams = new LayoutParams(mWeight, mHeight);
mLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
mLine.setLayoutParams(mLayoutParams);
setAnimation(mEndAddress, way);
mEndAddress = way;
this.mNowPosition = position;
}
- XML部分属性
线的颜色 : indicatorColor (默认red)
textview显示数组 :array
字体默认颜色:text_nomal_color (默认gray)
字体选中颜色:text_press_color (默认black)
字体默认大小:text_press_color (默认12)
字体选中大小:text_press_size (默认13)
默认选中:selected (默认0)
线是否铺满:isFull (默认false)
移动速度:speed (默认300)
线是字体的倍数:multiply (默认1.2)
线的高度: multiply (默认5)
====================================================================
- JAVA代码
/**
-
Created by huangbo on 17/1/22.
-
指示器
*/
public class MyIndicator extends RelativeLayout {
/**
- 线的颜色
*/
private int mColor;
/**
- 线的高度
*/
private int mHeight;
/**
- xml数组
*/
private String[] mList;
/**
- textview数组
*/
private List mTextList = new ArrayList<>();
/**
- string数组
*/
private List mListTitle = new ArrayList<>();
/**
- 默认字体大小
*/
private int mTextNomal;
/**
- 被选择字体大小
*/
private int mTextPress;
/**
- 默认字体颜色
*/
private int mText_Nomal;
/**
- 被选择的颜色
*/
private int mText_Press;
/**
- 每个格子个长度
*/
private int mContWidth;
/**
- 被选择的tab
*/
private int mSelected;
/**
- 底线
*/
private View mLine;
/**
- 是否或去过
*/
private boolean mIsCheck;
/**
- 字体的多少倍
*/
private float mBai;
/**
- 记录移动结束位置
*/
private int mEndAddress;
/**
- 禁止滑动表情下标
*/
private int mProhibitPisition = -1;
/**
- 动画时间
*/
private int mAnimationTime;
/**
- 当前选中
*/
private int mNowPosition;
/**
- 是否铺满
*/
private boolean isFull;
public MyIndicator(Context context) {
this(context, null);
}
public MyIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.setGravity(Gravity.CENTER_VERTICAL);
this.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.Indicator, 0, 0);
mColor = array.getColor(R.styleable.Indicator_indicatorColor, Color.RED);
mList = getContext().getResources().getStringArray(array.getResourceId(R.styleable.Indicator_array, 0));
mTextNomal = array.getInteger(R.styleable.Indicator_text_nomal_size, 12);
mTextPress = array.getInteger(R.styleable.Indicator_text_press_size, 13);
mText_Nomal = array.getColor(R.styleable.Indicator_text_nomal_color, Color.GRAY);
mText_Press = array.getColor(R.styleable.Indicator_text_press_color, Color.BLACK);
mSelected = array.getInteger(R.styleable.Indicator_selected, 0);
isFull = array.getBoolean(R.styleable.Indicator_isFull, false);
mAnimationTime = array.getInteger(R.styleable.Indicator_speed, 300);
mBai = array.getFloat(R.styleable.Indicator_multiply, (float) 1.2);
mHeight = array.getInteger(R.styleable.Indicator_line_hegith, 5);
for (int i = 0; i < mList.length; i++) {
mListTitle.add(mList[i]);
}
array.recycle();
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (!mIsCheck) {
mIsCheck = true;
initView();
}
}
/**
- 初始化布局
*/
private void initView() {
measure(0, 0);
//获取每个textview布局所占的宽度
mContWidth = getWidth() / mListTitle.size();
//添加线
mLine = new View(getContext());
addView(mLine);
int mWeight;
if (isFull) {
mWeight = mContWidth;
} else {
mWeight = (int) (setLineLength(mListTitle.get(mSelected)) * mBai);
if (mWeight > mContWidth) {
mWeight = mContWidth;
}
}
//设置线的基本属性
LayoutParams mLayoutParams1 = new LayoutParams(mWeight, mHeight);
mLayoutParams1.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
mLine.setLayoutParams(mLayoutParams1);
mLine.setBackgroundColor(mColor);
//获取上一次所在位置
mEndAddress = mContWidth * mSelected + (mContWidth - mWeight) / 2;
//添加textview
for (int i = 0; i < mListTitle.size(); i++) {
addTextView(i);
}
//初始化点击事件
setListener();
}
/**
- 添加textview
*/
private void addTextView(int i) {
//初始化textview
TextView textView = new TextView(getContext());
textView.setText(mListTitle.get(i));
//设置textview基本属性
LayoutParams mLayoutParams = new LayoutParams(mContWidth, LayoutParams.MATCH_PARENT);
mLayoutParams.leftMargin = mContWidth * i;
mLayoutParams.addRule(CENTER_VERTICAL);
textView.setLayoutParams(mLayoutParams);
textView.setGravity(Gravity.CENTER);
if (i == mSelected) {
textView.setTextColor(mText_Press);
textView.setTextSize(mTextPress);
} else {
textView.setTextColor(mText_Nomal);
textView.setTextSize(mTextNomal);
}
//添加textview到布局
mTextList.add(textView);
addView(textView);
}
/**
- 清空字体颜色
*/
private void resetColor() {
for (int i = 0; i < mTextList.size(); i++) {
mTextList.get(i).setTextColor(getContext().getResources().getColor(R.color.text_hint));
}
}
/**
- 点击tab事件
*/
private void setListener() {
setAnimation(0, mEndAddress);
for (int i = 0; i < mTextList.size(); i++) {
final int finalI = i;
mTextList.get(i).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (finalI != mSelected && mProhibitPisition != finalI) {
setChanger(finalI);
}
尾声
最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
这里,笔者分享一份从架构哲学的层面来剖析的视频及资料分享给大家梳理了多年的架构经验,筹备近6个月最新录制的,相信这份视频能给你带来不一样的启发、收获。
Android进阶学习资料库
一共十个专题,包括了Android进阶所有学习资料,Android进阶视频,Flutter,java基础,kotlin,NDK模块,计算机网络,数据结构与算法,微信小程序,面试题解析,framework源码!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
e(); i++) {
final int finalI = i;
mTextList.get(i).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (finalI != mSelected && mProhibitPisition != finalI) {
setChanger(finalI);
}
尾声
最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
这里,笔者分享一份从架构哲学的层面来剖析的视频及资料分享给大家梳理了多年的架构经验,筹备近6个月最新录制的,相信这份视频能给你带来不一样的启发、收获。
[外链图片转存中…(img-dopX8f0y-1715141476219)]
Android进阶学习资料库
一共十个专题,包括了Android进阶所有学习资料,Android进阶视频,Flutter,java基础,kotlin,NDK模块,计算机网络,数据结构与算法,微信小程序,面试题解析,framework源码!
[外链图片转存中…(img-0WhwQ7dB-1715141476221)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!