Android自定义View 实现图片轮播

第一次写博客 大家多多交流

最近项目需要图片论播,本来可以使用ViewPager实现 但是ViewPager没有循环播放的效果,而且日后项目当中还会有很大的机会用到这样的功能,自己造一下轮子,对自己的锻炼也有好处,所以自己实现了一个。对于代码当中的问题,欢迎大家指出

效果

device-2016-04-11-192359.gif

源码


源码上传到了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 来计算的 不是绝对位置

最后


谢谢大家阅读,有问题和我交流

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容