爲了實現廣告輪播功能,在網上找了不少方法,有的效果很好,可是代碼太麻煩,而且大可能是用的viewpager,總之不是很滿意。html
因而看了一下sdk有個控件是ViewFlipper,使用比較方便,因而嘗試了一下,最終實現了所需效果。在這裏與你們分享。java
首先看一下效果(主要是佈局方面的效果,畢竟手勢識別和滑動不太好顯示,懶得弄成gif了):android
一、佈局文件.xml數組
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"> <ViewFlipper android:layout_width="fill_parent" android:layout_height="120dp" android:id="@+id/details" > </ViewFlipper> <RelativeLayout android:layout_width="fill_parent" android:layout_height="16dp" > <LinearLayout android:layout_width="fill_parent" android:layout_height="16dp" android:orientation="horizontal" android:gravity="right" > <View android:id="@+id/v_dot0" style="@style/dot_style" android:background="@drawable/dot_focused" /> <View android:id="@+id/v_dot1" style="@style/dot_style" /> <View android:id="@+id/v_dot2" style="@style/dot_style" /> </LinearLayout> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="left" android:text="hello" /> </RelativeLayout> </LinearLayout>
我來解釋一下這個佈局網絡
首先,最外層是一個LinearLayout佈局來填充整個屏幕。 app
第二層就是控件ViewFlipper與RelativeLayout並列。其中ViewFlipper是實現圖片輪播的,RelationLayout是圖片下面的信息,好比圖片的標題(如圖中的&&)和圖片在全部圖片中的位置(表現形式爲最右邊的白色小點)ide
第三層其實就是把第二層的RelativeLayout展開,裏面有一個TextView控件來顯示標題,和三個View控件來顯示小點。佈局
下面是要用到的一些style和drawable代碼(該部分代碼來自網絡):spa
前5個放在res/drawable文件夾下orm
一、btn_back_selector.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/btn_top_pressed" android:state_focused="true"></item> <item android:drawable="@drawable/btn_top_pressed" android:state_pressed="true"></item> <item android:drawable="@drawable/btn_top_pressed" android:state_selected="true"></item> <item android:drawable="@drawable/title_bk"></item> </selector>
二、btn_top_pressed.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <gradient android:angle="270" android:endColor="#009ad6" android:startColor="#11264f" /> </shape>
三、dot_focused.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" > <solid android:color="#aaFFFFFF" /> <corners android:radius="5dip" /> </shape>
四、dot_normal.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" > <solid android:color="#33000000" /> <corners android:radius="5dip" /> </shape>
五、title_bk.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <gradient android:angle="270" android:endColor="#11264f" android:startColor="#009ad6" /> </shape>
六、styles.xml(放在values文件夾之下)
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="dot_style"> <item name="android:layout_width">5dip</item> <item name="android:layout_height">5dip</item> <item name="android:background">@drawable/dot_normal</item> <item name="android:layout_marginLeft">1.5dip</item> <item name="android:layout_marginRight">1.5dip</item> </style> </resources>
這上面的代碼我也不怎麼懂,可是目的就是爲了操做那些小點點。
下面問題來了,java代碼呢。不要急,這就上來。
下面高能,膽小誤入。
java代碼(先全都發上來,容我慢慢解釋)
package com.example.mynews; import java.util.ArrayList; import java.util.List; import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup.LayoutParams; import android.widget.ImageView; import android.widget.ImageView.ScaleType; import android.widget.TextView; import android.widget.Toast; import android.widget.ViewFlipper; public class MainActivity extends Activity{ private ViewFlipper viewFlipper; private String[] titles; private TextView tv_title; private List<View> dots; float startx; float x = 0; float y = 0; @Override @SuppressWarnings("deprecation") protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewFlipper = (ViewFlipper)findViewById(R.id.details); tv_title = (TextView)findViewById(R.id.title); int image[] = new int[] { R.drawable.a,R.drawable.b,R.drawable.c }; for(int i=0;i<image.length;i++) { ImageView iv = new ImageView(getApplicationContext()); iv.setBackgroundResource(image[i]); iv.setScaleType(ScaleType.CENTER_INSIDE); iv.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT)); viewFlipper.addView(iv); } titles = new String[image.length]; titles[0] = "hello"; titles[1] = "&&"; titles[2] = "world"; dots = new ArrayList<View>(); dots.add(findViewById(R.id.v_dot0)); dots.add(findViewById(R.id.v_dot1)); dots.add(findViewById(R.id.v_dot2)); handler.sendMessageDelayed(new Message(), 5000); viewFlipper.setOnTouchListener(new OnTouchListener() { @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub switch(event.getAction()) { case MotionEvent.ACTION_DOWN: { x = event.getX(); Toast.makeText(getApplicationContext(), "down"+event.getX(), 1).show(); }break; case MotionEvent.ACTION_UP: { y = event.getX(); if(y>x) { Log.v(null, "result:y>x"); showPre(); } else if(x==y) { Log.v(null, "result:y=x"); showDetail(); } else { Log.v(null, "result:x>y"); showNext(); } }break; } return true; } }); } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); showNext(); handler.sendMessageDelayed(new Message(), 5000); } }; private void showNext() { viewFlipper.showNext(); int cur = viewFlipper.getDisplayedChild(); if(cur == 0) { dots.get(2).setBackgroundResource(R.drawable.dot_normal); } else { dots.get(cur-1).setBackgroundResource(R.drawable.dot_normal); } dots.get(cur).setBackgroundResource(R.drawable.dot_focused); tv_title.setText(titles[cur]); } private void showPre() { viewFlipper.showPrevious(); int cur = viewFlipper.getDisplayedChild(); if(cur == 2) { dots.get(0).setBackgroundResource(R.drawable.dot_normal); } else { dots.get(cur+1).setBackgroundResource(R.drawable.dot_normal); } dots.get(cur).setBackgroundResource(R.drawable.dot_focused); tv_title.setText(titles[cur]); } private void showDetail() { Toast.makeText(getApplicationContext(),"x=y", 1).show(); } }
一、先準備圖片,這裏我準備了三張,初始化代碼以下:
int image[] = new int[]//用int型數組來儲存三張照片的編號 { R.drawable.a,R.drawable.b,R.drawable.c }; for(int i=0;i<image.length;i++)//將三張照片加入viewflipper裏 { ImageView iv = new ImageView(getApplicationContext()); iv.setBackgroundResource(image[i]); iv.setScaleType(ScaleType.CENTER_INSIDE);//這裏設置圖片變換格式 iv.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT)); viewFlipper.addView(iv); }
二、對ViewFlipper設置監聽事件(進行手勢操做的核心),注意,這裏的監聽不是onclicklistener,而是ontouchlistener
viewFlipper.setOnTouchListener(new OnTouchListener() { @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub switch(event.getAction()) { case MotionEvent.ACTION_DOWN://手指按下 { x = event.getX();//全局變量,接收按下是的手指座標 Toast.makeText(getApplicationContext(), "down"+event.getX(), 1).show(); }break; case MotionEvent.ACTION_UP://手指鬆開 { y = event.getX();//全局變量,接收鬆開是的手指座標 //下面就是簡單的邏輯判斷,從而區分向左滑、向右滑以及不滑(也就是點擊事件) if(y>x) { Log.v(null, "result:y>x"); showPre(); } else if(x==y) { Log.v(null, "result:y=x"); showDetail(); } else { Log.v(null, "result:x>y"); showNext(); } }break; } return true; } });
這裏要重點說下,原本我採用的不是這種方法,而是將activity使用ontouch接口、ViewFlipper使用onclicklistener,並且還要聲明一個gesturedetector變量,這樣會出現一個問題,就是ontouch與onclick的事件會相互影響,具體怎麼回事,我也沒搞明白。有事件會仔細研究研究。此外,若是使用gesturedetector又會增長複雜度。
而後是圖片切換動做,也就是上段代碼中的showPre()、showNext()、showDetail()方法。做用分別是向左滑、向右滑、不滑(這裏能夠用來實現點擊事件)代碼以下:
private void showNext() { viewFlipper.showNext();//sdk封裝好的,使用很是方便 int cur = viewFlipper.getDisplayedChild(); if(cur == 0) { dots.get(2).setBackgroundResource(R.drawable.dot_normal);//這是控制那些小點點的,邏輯應該能看懂,就不解釋了 } else { dots.get(cur-1).setBackgroundResource(R.drawable.dot_normal); } dots.get(cur).setBackgroundResource(R.drawable.dot_focused); tv_title.setText(titles[cur]); } private void showPre() { viewFlipper.showPrevious();//sdk封裝好的,使用很是方便 int cur = viewFlipper.getDisplayedChild(); if(cur == 2) { dots.get(0).setBackgroundResource(R.drawable.dot_normal); } else { dots.get(cur+1).setBackgroundResource(R.drawable.dot_normal); } dots.get(cur).setBackgroundResource(R.drawable.dot_focused); tv_title.setText(titles[cur]); } private void showDetail() { Toast.makeText(getApplicationContext(),"x=y", 1).show(); }
下面又到了另一個重點,handler機制,其實和定時器差很少(至少在這裏是)
handler.sendMessageDelayed(new Message(), 5000);
沒5000ms也就是5s發送一次消息,這個消息是幹嗎的?請看下端代碼
private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); showNext(); handler.sendMessageDelayed(new Message(), 5000); } };
簡單的講,它是給他本身發消息,提醒本身時間到了,該吃藥了(該作某件事了)。而後作完以後還要告訴本身,過5s還要吃藥,就這樣一直吃藥,不放棄治療。
我想,說到這裏,應該明白,這段代碼的功能就是實現圖片的自動切換。
至此,代碼的重點部分解釋完了。至於標題和那些小點點怎麼處理,都在那三個方法裏寫好了,確定能夠看明白,就很少贅述了。
附:
一、代碼出問題儘可能不要找我,雖然是我寫的,可是它本身長歪了。
二、轉載請註明出處。
謝謝閱讀,歡迎批評指正。