Android 經過ViewFlipper實現廣告輪播功能並能夠經過手勢滑動進行廣告切換

爲了實現廣告輪播功能,在網上找了不少方法,有的效果很好,可是代碼太麻煩,而且大可能是用的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還要吃藥,就這樣一直吃藥,不放棄治療。

我想,說到這裏,應該明白,這段代碼的功能就是實現圖片的自動切換。 

 

至此,代碼的重點部分解釋完了。至於標題和那些小點點怎麼處理,都在那三個方法裏寫好了,確定能夠看明白,就很少贅述了。

 

附:

一、代碼出問題儘可能不要找我,雖然是我寫的,可是它本身長歪了。

二、轉載請註明出處。

 

謝謝閱讀,歡迎批評指正。 

相關文章
相關標籤/搜索