(原来可以这么简单)实现变色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文件:
第一步:还是继承一个ViewGroup,覆盖三个构造方法,(有种东西叫熟能生巧,所以,骚年加油!!)
第二步:设置titles,并获取线条的宽度=控件宽度/子控件个数
第三步:也是重点一步,绘制line
第四步:暴露方法供外部调用,从而不断切换item
第五步:测试成果
是不是so easy啊!!只要坚持,并不断的总结,我相信你会成为大神的,哈哈~!!
最后附上SimpleViewPagerIndicator的源码:
思路:
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); } } }
}
相关文章推荐
- 实现变色TextView及ViewPager指示器(原来可以这么简单)
- 简单viewpager布局加fragment联动 可以实现效果
- TextView实现跑马灯效果 就这么简单!
- 原来操控界面可以这么简单----安卓上下滑动缩放顶部图片,左右滑动结束当前Activity,及View柔和回弹效果
- 原来这么简单就可以实现无纸化办公
- 关于ViewPager当前页卡指示器的简单实现方法
- 打造最简单ViewPager指示器,实现小圆点效果
- ViewPager 实现页面左右滑动的简单案例1
- 原来设置ICSharpCode.TextEditor语法高亮这么简单
- TextView中实现跑马灯的最简单方法
- android 实现可以放大缩小的TextView
- Android中TextView不获取焦点可以实现跑马灯的效果
- 当TextView或者EditView的内容发生变化时,其他组件及时给予响应时,我们可以使用TextWatcher来实现。
- 简单的TextView自定义控件,实现左右加减按钮
- 使用ViewPager实现图片左右切换(有实心和空心和TextView随图片改变而改变)
- 自定义的带tab的可左右滑动的viewpager之一 简单实现
- JAVA中BCD码的转化问题:原来可以这么简单
- 用最简单最实用的方式实现ViewPager无限循环两种方式
- 利用.NET做“电子书阅读器”原来这么简单(其实你也可以做出金山词霸)