第一次写博客 大家多多交流
最近项目需要图片论播,本来可以使用ViewPager实现 但是ViewPager没有循环播放的效果,而且日后项目当中还会有很大的机会用到这样的功能,自己造一下轮子,对自己的锻炼也有好处,所以自己实现了一个。对于代码当中的问题,欢迎大家指出
效果
源码
源码上传到了github 欢迎大家在github上和我交流 地址
使用方法 直接把library 当中的ImageSwitch 放进你的项目当中就可以了
关键代码展示:
//layout child view
// 这里使用了3个子view 来展示内容,其中第二个子view放置在中间,作为正在显示的内容.
//第1和第3的子view 分别表示正在显示的子view 的左边 右边第一个.
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
System.out.println("l "+l+" r "+r);
ViewGroup parent= (ViewGroup) getParent();
this.l=0+getPaddingLeft();
this.t=0+getPaddingTop();
this.r=r-l-getPaddingRight();
this.b=b-getPaddingBottom();
int ll=this.l;
width=this.r-this.l;
for(int i=0;i<getChildCount();++i){
//layout the child in right position
View child=getChildAt(i);
if(childs[0].equals(child)){
//The child should be put int left;
child.layout(-width,this.t,0,this.b);
}
if(childs[1].equals(child)){
//The child should be put int middle
child.layout(this.l,this.t,this.r,this.b);
}
if(childs[2].equals(child)){
child.layout(getWidth(),this.t,getWidth()+width,this.b);
}
}
}
子view 之间的切换处理
主要有三个步骤
1.计算子view的移动距离
2.使用属性动画(不同与补间动画,这里可以实际上的改变对象的属性)对view进行移动处理
3.移动完成(等同于动画完成)之后,更新当前的位置,绑定下一个位置的数据
//这里是向左移动子view
private void changeToNext(){
if(isAnimation ||isTouching){
return;
}
isAnimation =true;
//计算第二个view 需要移动的距离
int translation0=childs[1].getRight();
//计算第三个view 需要移动的距离
int translation1=childs[2].getLeft()-childs[1].getLeft();
// System.out.println(childs[1].hashCode()+": left "+childs[1].getLeft()+" right "+childs[1].getRight()+" tx "+childs[1].getTranslationX());
// System.out.println(childs[2].hashCode()+": left "+childs[2].getLeft()+" right "+childs[2].getRight()+" tx "+childs[2].getTranslationX());
// System.out.println("================== before =======================");
//使用属性动画对子view 进行切换
PropertyValuesHolder translationHolder=PropertyValuesHolder.ofFloat("translationX",-translation0);
PropertyValuesHolder alphaHolder=PropertyValuesHolder.ofFloat("alpha",0.6f);
ObjectAnimator dismissAnimator=ObjectAnimator.ofPropertyValuesHolder(childs[1],translationHolder,alphaHolder);
dismissAnimator.setDuration(animationDuration).start();
ObjectAnimator occurAnimator=ObjectAnimator.ofFloat(childs[2],"translationX",-translation1);
occurAnimator.setDuration(animationDuration);
occurAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
// System.out.println("*************** after *************");
// System.out.println(childs[1].hashCode()+": left "+childs[1].getLeft()+" right "+childs[1].getRight()+" tx "+childs[1].getTranslationX());
// System.out.println(childs[2].hashCode()+": left "+childs[2].getLeft()+" right "+childs[2].getRight()+" tx "+childs[2].getTranslationX());
// System.out.println("$$$$$$$$$$$$$$$$ after $$$$$$$$$$$$$$");
reLayoutRight();
++curentPosition;
curentPosition=curentPosition% adapter.getCount();
adapter.onItemChanged(curentPosition);
int np=(curentPosition+1)% adapter.getCount();
adapter.bindData(childs[2],np);
// np=curentPosition-1;
// np=np<0? adapter.getCount()-1:np;
// adapter.bindData(childs[0],np);
isAnimation =false;
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
occurAnimator.start();
}
向右移动的原理和向左移动的原理相同,这里就不详述了,具体可以刀github 上看我详细的代码
Adapter 的设计
public interface Adapter {
/*
* use to create the item
* return : return the item it created
* */
View createItem();
/*
* bindData for the view
* @param
* view :target
* position: position of the view
* */
void bindData(View view, int position);
/*
* get the count of child
* return :
* return the count for the child;
* */
int getCount();
void onItemChanged(int currentItem);
}
Adpater 只有3个方法
1.createItem 是一个工厂方法,负责创建child view
2.bindData 负责绑定数据
3.onItemChanged 是一个回调方法,传入的参数是当前显示的item 的位置
使用方法
ImageSwitcher iser;
...
...
Adapter adapter =new Adapter(){
//实现Adapter 里面的方法
}
//设置Adapter
iser.setAdapter(adapter);
//可以在Activity onResume 当中使用该方法
void onResume(){
iser.start(1000//传入的是子view 之间的动画切换间隔)
}
void onStop(){
//在activity onStop 的时候 调用这个方法可以放置内存泄露
iser.stop()
}
项目特点
1.内容分离:不关心具体内容如何实现,这个由程序员控制。只要显示的内容继承自View即可
2.View重用:只会创建3个View用来显示内容,不会因为轮播的内容过多而创建过多的View 从而影响性能
3.支持滑动:支持用户滑动操作
项目结构简要说明
项目架构主要由三个类(接口)架设起来:
1.ImageSwitch :负责Layout 内容,内容切换,过渡动画
2.Timer:负责控制内容切换的时间间隔
3.Adapter:负责创建内容 动态绑定内容数据
遇到的一些问题
1.View.setTranslationX() 方法设置View的移动位置,但是View 的left right 并没有改变 。setTranslationY() 同样如此
2.View.layout() 方法可以改变View 的left right top bottom的位置。
3 View 当中的left right top bottom 的位置是相对与 View 当前parent 来计算的 不是绝对位置
最后
谢谢大家阅读,有问题和我交流