您的位置:首页 > 其它

(原来可以这么简单)实现变色TextView及ViewPager指示器(二)

2016-08-11 21:40 796 查看
上篇实现了FadeTextView可变色的textView,今天结合ViewPager做一个指示器,运行效果可以见上篇博客:实现变色TextView及ViewPager指示器(原来可以这么简单)

思路:

1、自定义一个叫SimpleViewPagerIndicator继承ViewGroup。

2、根据传入的titles创建FadeView,水平摆放置布局中,布局最底下用画笔绘制一条线,

3、监听ViewPager的滑动,setOnPageChangeListener,根据onPageScrolled方法计算线条绘制的位置以及FadeTextView的颜色变换

测试layout文件:

<com.cisetech.customer.customer.Animation.SimpleViewPagerIndicator
android:id="@id/id_stickylayout_nav"
android:layout_width="match_parent"
android:layout_height="50dp">
</com.cisetech.customer.customer.Animation.SimpleViewPagerIndicator>
<android.support.v4.view.ViewPager
android:id="@id/id_stickylayout_viewpager"
android:layout_width="match_parent"
android:background="#44ff0000"
android:layout_height="match_parent">

</android.support.v4.view.ViewPager>


第一步:还是继承一个ViewGroup,覆盖三个构造方法,(有种东西叫熟能生巧,所以,骚年加油!!)

/**
* 定义当点击每个FadeTextView的回调接口
*/
public interface OnIndicatorClickListener{
void indicatorClick(View view,int position);
}
private OnIndicatorClickListener onIndicatorClickListener;

public void setOnIndicatorClickListener(OnIndicatorClickListener onIndicatorClickListener) {
this.onIndicatorClickListener = onIndicatorClickListener;
}

/**
* titles
*/
private String[]titles;
private Paint mPaint;
/**
* 线条的宽度=控件的宽度/子控件的个数
*/
private float mLineWidth;
/**
* 距离底部的Padding值,可忽略
*/
private int mLinePading= (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics());
/**
* 底部线条绘制的开始位置
*/
private float mLineStartX;

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

public SimpleViewPagerIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public SimpleViewPagerIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setDither(true);
mPaint.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mLinePading, getResources().getDisplayMetrics()));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.RED);
setOrientation(LinearLayout.HORIZONTAL);
}
}


第二步:设置titles,并获取线条的宽度=控件宽度/子控件个数

/**
* 当控件的size发生变化的时候会调用此方法
* 一般在这获取控件的宽高
* 我们在这获取线条的宽度
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mLineWidth=w/titles.length;
}
/**
* 设置titles
*/
public void setTitles(String[] titles) {
this.titles = titles;
setupTitles();
}

/**
*添加titles到父控件中,
* 并给每个子控设置点击监听
*/
private void setupTitles() {
if (getChildCount() > 0)
this.removeAllViews();
setWeightSum(titles.length);
for (int i = 0; i < titles.length; i++) {
final int j=i;
final FadeView textView=new FadeView(getContext());
LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(0,LayoutParams.MATCH_PARENT);
lp.weight=1;
textView.setLayoutParams(lp);
textView.setmText(titles[i]);
textView.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
if(onIndicatorClickListener!=null){
onIndicatorClickListener.indicatorClick(v, j);
}
}
});
addView(textView);
}
}


第三步:也是重点一步,绘制line

/**
* 重写dispatchDraw方法绘制底部线条
*/
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.save();
/**
* 通过平移canvas移动线条位置
* mLineStartX
*/
canvas.translate(mLineStartX,getHeight()-mLinePading);
canvas.drawLine(0, 0, mLineWidth, 0, mPaint);
canvas.restore();
}


第四步:暴露方法供外部调用,从而不断切换item

/**
* 通过监听ViewParger传进来当前ViewPager位置,
* 以及偏移量(0-1)
* 当从第0页切换到第一页的时候 position(int 0-1)offset(float 0-1)
*/
public void setOffset(final int position, final float positionOffset) {
/**
* 线条开始的位置=线条的宽度*position+mLineWidth*positionOffset
* 数学一样跟我不是很好的同学可以打个log看看值就懂了
*/
float startX = mLineWidth * (position + positionOffset);
setmLineStartX(startX);
/**
* 为什么是小于0.1呢,mPager.setCurrentItem(position,true);
* 比如当前ViewPager位置是3,然后切换到0,跨了一个item,
* 有点小bug,所以测试了一下当《0.1的,状态都重新切换一次就不会有bug了
* 如果是mPager.setCurrentItem(position,false);不用动画切换的是不会有bug的
*/
if (positionOffset < 0.1) {
for (int k = 0; k < getChildCount(); k++) {
FadeView fade = (FadeView) getChildAt(k);
if (position == k) {
fade.setmProgress(1.0f);
} else {
fade.setmProgress(0f);
}
}
} else {
FadeView left = (FadeView) getChildAt(position);
FadeView right = (FadeView) getChildAt(position + 1);
if (left != null) {
left.setmDirection(FadeView.DIRECTION.RIGHT);
left.setmProgress(1 - positionOffset);
}
if (right != null) {
right.setmDirection(FadeView.DIRECTION.LEFT);
right.setmProgress(positionOffset);
}
}
}


第五步:测试成果

private SimpleViewPagerIndicator mIndicator;
private ViewPager mPager;
private List<Fragment> mViews=new ArrayList<Fragment>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test4);
mIndicator= (SimpleViewPagerIndicator) findViewById(R.id.id_stickylayout_nav);
mPager= (ViewPager) findViewById(R.id.id_stickylayout_viewpager);
initData();
}
private String titles[]={"简介","评价","相关"};
private void initData() {
mIndicator.setTitles(titles);
for (int i = 0; i < 3; i++) {
TabFragment frag=TabFragment.newInstance(titles[i]);
Bundle bundle=new Bundle();
bundle.putString(TabFragment.TITLE,titles[i]);
frag.setArguments(bundle);
mViews.add(frag);
}
mPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return mViews.get(position);
}

@Override
public int getCount() {
return mViews.size();
}
});
mPager.setOnPageChangeListener(this);
mIndicator.setOnIndicatorClickListener(this);
}

@Override
public void onPageScrolled(final int position, final float positionOffset, int positionOffsetPixels) {
mIndicator.setOffset(position, positionOffset);
}

@Override
public void onPageSelected(int position) {

}

@Override
public void onPageScrollStateChanged(int state) {

}

@Override
public void indicatorClick(View view, final int position) {
mPager.setCurrentItem(position,false);
}


是不是so easy啊!!只要坚持,并不断的总结,我相信你会成为大神的,哈哈~!!

最后附上SimpleViewPagerIndicator的源码:

package com.cisetech.customer.customer.Animation;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.widget.LinearLayout;

import com.cisetech.customer.customer.View.FadeView;

/**
* Author:Yqy
* Date:2016-08-05
* Desc:
* Company:cisetech
*/
public class SimpleViewPagerIndicator extends LinearLayout {
/**
* 定义当点击每个FadeTextView的回调接口
*/
public interface OnIndicatorClickListener{
void indicatorClick(View view,int position);
}
private OnIndicatorClickListener onIndicatorClickListener;

public void setOnIndicatorClickListener(OnIndicatorClickListener onIndicatorClickListener) {
this.onIndicatorClickListener = onIndicatorClickListener;
}

/**
* titles
*/
private String[]titles;
private Paint mPaint;
/**
* 线条的宽度=控件的宽度/子控件的个数
*/
private float mLineWidth;
/**
* 距离底部的Padding值,可忽略
*/
private int mLinePading= (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics());
/**
* 底部线条绘制的开始位置
*/
private float mLineStartX;

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

public SimpleViewPagerIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public SimpleViewPagerIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setDither(true);
mPaint.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mLinePading, getResources().getDisplayMetrics()));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.RED);
setOrientation(LinearLayout.HORIZONTAL);
}

public String[] getTitles() {
return titles;
}

/**
* 设置titles
*/
public void setTitles(String[] titles) {
this.titles = titles;
setupTitles();
}

public float getmLineStartX() {
return mLineStartX;
}

public void setmLineStartX(float mLineStartX) {
this.mLineStartX = mLineStartX;
if(Looper.getMainLooper()==Looper.myLooper()){
invalidate();
}else{
postInvalidate();
}
}

/**
*添加titles到父控件中,
* 并给每个子控设置点击监听
*/
private void setupTitles() {
if (getChildCount() > 0)
this.removeAllViews();
setWeightSum(titles.length);
for (int i = 0; i < titles.length; i++) {
final int j=i;
final FadeView textView=new FadeView(getContext());
LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(0,LayoutParams.MATCH_PARENT);
lp.weight=1;
textView.setLayoutParams(lp);
textView.setmText(titles[i]);
textView.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
if(onIndicatorClickListener!=null){
onIndicatorClickListener.indicatorClick(v, j);
}
}
});
addView(textView);
}
}

/**
* 当控件的size发生变化的时候会调用此方法
* 一般在这获取控件的宽高
* 我们在这获取线条的宽度
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mLineWidth=w/titles.length;
}

/** * 重写dispatchDraw方法绘制底部线条 */ @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); canvas.save(); /** * 通过平移canvas移动线条位置 * mLineStartX */ canvas.translate(mLineStartX,getHeight()-mLinePading); canvas.drawLine(0, 0, mLineWidth, 0, mPaint); canvas.restore(); }

/** * 通过监听ViewParger传进来当前ViewPager位置, * 以及偏移量(0-1) * 当从第0页切换到第一页的时候 position(int 0-1)offset(float 0-1) */ public void setOffset(final int position, final float positionOffset) { /** * 线条开始的位置=线条的宽度*position+mLineWidth*positionOffset * 数学一样跟我不是很好的同学可以打个log看看值就懂了 */ float startX = mLineWidth * (position + positionOffset); setmLineStartX(startX); /** * 为什么是小于0.1呢,mPager.setCurrentItem(position,true); * 比如当前ViewPager位置是3,然后切换到0,跨了一个item, * 有点小bug,所以测试了一下当《0.1的,状态都重新切换一次就不会有bug了 * 如果是mPager.setCurrentItem(position,false);不用动画切换的是不会有bug的 */ if (positionOffset < 0.1) { for (int k = 0; k < getChildCount(); k++) { FadeView fade = (FadeView) getChildAt(k); if (position == k) { fade.setmProgress(1.0f); } else { fade.setmProgress(0f); } } } else { FadeView left = (FadeView) getChildAt(position); FadeView right = (FadeView) getChildAt(position + 1); if (left != null) { left.setmDirection(FadeView.DIRECTION.RIGHT); left.setmProgress(1 - positionOffset); } if (right != null) { right.setmDirection(FadeView.DIRECTION.LEFT); right.setmProgress(positionOffset); } } }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: