生活中我們不難發現一些電商類的app裏面都會有一些輪播的廣告條出現,我有位好朋友他正巧就是做商城這方面的app,那時候他也要做一個類似淘寶界面上的輪播的滾動條,當時他是採用listview來實現此效果,最近有空研究了一下,發現Android有些原生控件完全可以實現此功能,並且還可以實現其它更強大的效果。
如上圖所示我們可以使用Android原生控件ViewAnimator
下的幾個子控件去實現。通過官方文檔我們可以發現ViewAnimator
有兩個直接子類(ViewFlipper
、ViewSwitcher
)和兩個間接子類(ImageSwitcher
、TextSwitcher
),說實話在之前的開發中,我竟然不知道這幾個控件,真是汗顏。對於上圖的效果我們可以通過其子類ViewFlipper
來去實現。
ViewFlipper實現上下輪播廣告條
ViewFlipper
可以將動畫添加到兩個或多個試圖之中,每次只能顯示一個試圖。當然我們可以控制試圖之間的交換。
<ViewFlipper
android:id="@+id/viewFlipper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inAnimation="@anim/in"
android:outAnimation="@anim/out"
android:flipInterval="2000"
android:autoStart="true"/>
android:inAnimation
進入時動畫android:outAnimation
退出時動畫android:flipInterval
跳轉的間隔時間android:autoStart
是否自動啓動startFlipping()
啓動一個定時器來循環子試圖stopFlipping()
停止子試圖的循環
JAVA代碼
//這裏我建了個News類 模擬從網絡上獲取數據 並展示
List<News> newsList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
News news = new News();
news.setFirstNews("我是第一行第" + i + "條數據");
news.setTwoNews("我是第二行第" + i + "條數據");
newsList.add(news);
}
for (News news : newsList) {
//創建試圖(這裏我就簡單的使用java代碼進行簡單的佈局創建,當然你也可以在xml中去創建它)
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setPadding(10,10,10,10);
TextView textView1 = new TextView(this);
TextView textView2 = new TextView(this);
textView1.setText(news.getFirstNews());
textView2.setText(news.getTwoNews());
linearLayout.addView(textView1);
linearLayout.addView(textView2);
//通過addView將試圖添加進去(有幾個試圖就必須添加幾個,否則無法展示)
viewFlipper.addView(linearLayout);
}
就這樣我們的文本廣告條就實現了,是不是很簡單,使用此控件去實現廣告條的效果真的很方便。當然它的功能遠不止這些,下面我通過此控件模仿ViewPager
實現生活中常見的banner效果。雖然實現了,但其效果還是不及ViewPager
的好,如果你們感興趣的話也可以自己研究研究,可能會有更好的方法去實現此功能。
ViewFlipper實現banner
<FrameLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="20dp">
<ViewFlipper
android:id="@+id/vf_banner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:flipInterval="3000"
android:autoStart="true"/>
<LinearLayout
android:id="@+id/point"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="10dp"
android:orientation="horizontal"/>
</FrameLayout>
Banner中的圓點
//選中時狀態
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/holo_red_dark"/>
</shape>
//默認狀態
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/white"/>
</shape>
//添加選擇器
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/circle"/>
<item android:state_selected="false" android:drawable="@drawable/circle_pre"/>
</selector>
JAVA代碼
這裏對於輪播狀態的監聽,在ViewFlipper
中確實沒有發現可行的監聽事件,於是我通過實現它的動畫的監聽事件根據ViewFlipper.getDisplayedChild()
獲取當前圖片的下標,從而去改變圓點的狀態。在實現左右滑動的效果時我採用的是實現onTouchEvent
方法去判斷它的起始點和結束點的距離,從而實現其左右切換,當然在切換的過程中我們可以添加動畫(這裏我沒有去實現,直接進行跳轉了),當然這裏我們也可以通過GestureDetector
來實現左右滑動,有興趣的可以試試下,效果應該比這個好些。
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(20,20);
params.leftMargin = 10;
//圖片資源
int[] imagsList = {R.mipmap.one,R.mipmap.banner,R.mipmap.ban,R.mipmap.two};
//循環添加試圖並創建圓點
for (int i : imagsList) {
ImageView imageView = new ImageView(this);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setImageResource(i);
//將試圖添加進去
flipperBanner.addView(imageView);
//創建圓點(有幾張圖片創建幾個)
TextView textView = new TextView(this);
//設置選擇器
textView.setBackgroundResource(R.drawable.choose_circle);
textView.setLayoutParams(params);
//添加圓點
linearLayout.addView(textView);
}
//默認選中第一個圓點
linearLayout.getChildAt(0).setSelected(true);
//添加動畫
flipperBanner.setInAnimation(this,R.anim.in_left);
flipperBanner.setOutAnimation(this,R.anim.out_left);
//設置監聽事件
flipperBanner.getOutAnimation().setAnimationListener(animationListener);
flipperBanner.setOnTouchListener(this);
//實現動畫的監聽事件
Animation.AnimationListener animationListener = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
//獲取當前下標,根據下標判斷狀態
point();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
//圓點的狀態
private void point() {
for (int i = 0; i < imagsList.length; i++) {
if (i == flipperBanner.getDisplayedChild()) {
linearLayout.getChildAt(flipperBanner.getDisplayedChild()).setSelected(true);
}else {
linearLayout.getChildAt(i).setSelected(false);
}
}
}
//模擬左右滑動狀態下圖片的改變
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
x1 = motionEvent.getX();//起始點
break;
case MotionEvent.ACTION_UP:
if(x1 - motionEvent.getX() > 20){
flipperBanner.showNext();
}else if (x1 - motionEvent.getX() < -20){
flipperBanner.showPrevious();
}else {
//實現其點擊事件
Toast.makeText(MainActivity.this,String.valueOf(flipperBanner.getDisplayedChild()),Toast.LENGTH_SHORT).show();
}
point();
break;
}
return true;
}
對於一些常見的廣告條我們基本上都可以通過ViewAnimator
下的子控件去實現它,其它的幾個子控件的功能也是相當神奇的,這裏也就試着寫了一個。有興趣的可以看下源碼。哈哈!