第一次寫博客 大家多多交流
最近項目需要圖片論播,本來可以使用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 來計算的 不是絕對位置
最后
謝謝大家閱讀,有問題和我交流