1. 程式人生 > >Android中Gallery和ImageSwitcher同步自動(滾動)播放圖片庫

Android中Gallery和ImageSwitcher同步自動(滾動)播放圖片庫

目標 art trac repl otto fin instance img com

本文主要內容是如何讓Gallery和ImageSwitcher控件能夠同步自動播放圖片集 ,看起來較難,然而,實現的方法非常簡單,

請跟我慢慢來。總的來說,本文要實現的效果如下圖:(截圖效果不怎麽好)

技術分享

本文是建立在以下兩篇bolg上的:

1、Android入門第十二篇之Gallery

2、Android 控件之ImageSwitcher圖片切換器

如果對Gallery和ImageSwitcher控件不是很熟悉的同學,建議先過去看看,本文並沒有怎麽講述控件的使用方法,而是在使用

基礎上,搭建我們的技巧。

接下來,溫習鞏固這兩個控件的知識點,有個知識性的儲備。

一、 Gallery的監聽事件

Gallery的兩個重要監聽事件如下:

1、OnItemClickListener 監聽事件

說明:當Gallery中的Item處於選中狀態並且被點擊觸發該事件 ;

其監聽方法為:

onItemClick

2、OnItemSelectedListener

監聽事件

說明:當Gallery中的Item處於選中狀態時觸發該事件

其監聽方法為:

public voidonItemSelected(AdapterView<?> parent, View view, int position, long id)

說明:當Gallery中的Item處於選中狀態時觸發該事件

public void onNothingSelected(AdapterView<?> parent)

說明:當控件沒有任何一項item選中時,觸發該方法

兩種監聽事件的區別在於,Item被選中(selected)的由來。其由來有兩種:

1、鼠標點擊(click)了Item (先click),然後該項selected ;

2、代碼設置某項Item 選中,例如setSelection(int position)(具體使用見下文) ,然後該項selected .

在情形1時,首先觸發OnItemClickListener(先click),接著便是OnItemSelectedListener監聽(因為item selected)。當某個Item

處於選中狀態時,如果它是由情形2而來,就不會觸發OnItemClickListener監聽(沒有click),只會觸發OnItemSelectedListener監聽

(只是selected)。

二、Gallery的setSelection()方法

方法原型: public void setSelection (int position)

說明:使第position處於選中狀態。同時觸發OnItemSelectedListener監聽事件。

PS: 在listView控件中也存在setSelection()是讓該行處於屏幕可見狀態,不需要手動滑動定位。第一次進入界面時,

默認顯示第一行,於是乎,我們可以手動設置該方法,ListView在顯示時,便可主動定位該item了。

準備材料已經上齊,相信通過前面的介紹,您一定對Gallery和ImageSwitcher控件很熟悉了,下面準備大餐!

步驟一:開啟一個線程,循環遍歷圖片集的資源id,並且將id發送至Hanlder對象。

步驟二:Handler接受到當前圖片資源的ID,調用setSelection (id)選中它(該Item selected),繼而setSelection()

觸發OnItemSelectedListener 事件,執行目標方法,這樣我們的目的就達到了。

下面,給出該Demo,希望能幫助大家更好的理解。

1 、 布局文件 main.xml

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical" android:layout_width="fill_parent"  
    android:layout_height="fill_parent">  
    <TextView android:layout_width="fill_parent"  
        android:layout_height="wrap_content" android:text="@string/hello" />  
    <ImageSwitcher android:id="@+id/myimgSwitcher" android:layout_gravity="center"  
        android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="20dip"></ImageSwitcher>  
    <Gallery android:id="@+id/mygallery" android:layout_width="fill_parent"  
        android:layout_height="wrap_content" android:background="#8A2BE2"></Gallery>  
</LinearLayout>  

2 、主文件 MainActivity.Java

package com.lover.qinjun;

import java.lang.reflect.Field;
import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ViewSwitcher.ViewFactory;

public class MainActivity extends Activity implements ViewFactory {
    private static String TAG = "Gallery_Auto";
    private static int MSG_UPDATE = 1;

    private int count_drawble = 0;
    private int cur_index = 0;
    private boolean isalive = true; 、//線程循環運行的條件 
    private ImageSwitcher imgSwitcher;
    private Gallery mgallery;
    // 為Gallery控件設置Adapter
    private ImageAdapter imgAdapter = null;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        imgSwitcher = (ImageSwitcher) findViewById(R.id.myimgSwitcher);
        mgallery = (Gallery) findViewById(R.id.mygallery);
        mgallery.setSpacing(3); //設置圖片之間的間隔,如果不加設置 ,圖片會疊加。設置為0,表示圖片之間無間縫。
        // 設置監聽事件 --->當Gallery中的Item處於選中並且被點擊觸發該事件 
        mgallery.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View view,
                    int position, long arg3) {
                System.out.println("setOnItemClickListener");
//                imgSwitcher.setBackgroundResource(imgAdapter.getResId(position));
            }
        });
        //當Gallery中的Item處於選中並且被點擊觸發該事件   ,在該監聽事件中,保證圖片播放的同步性
        mgallery.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> arg0, View view,
                    int position, long arg3) {
                 System.out.println("setOnItemSelectedListener");
                 //這兒不能通過setImageResource()設置圖片 
                 imgSwitcher.setBackgroundResource(imgAdapter.getResId(position));
            }
            @Override
            public void onNothingSelected(AdapterView<?> arg0) {

            }
        });
        //構建適配器,並且分配
        imgAdapter = new ImageAdapter(this);
        mgallery.setAdapter(imgAdapter);
        count_drawble = imgAdapter.getCount();

        // 利用線程來更新 當前欲顯示的圖片id, 調用handler來選中當前圖片
        new Thread(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (isalive) {
                    cur_index = cur_index % count_drawble;  // 圖片區間[0,count_drawable)
                    Log.i(TAG, "cur_index"+ cur_index +" count_drawble --"+ count_drawble);
                    //msg.arg1 = cur_index 
                    Message msg = mhandler.obtainMessage(MSG_UPDATE, cur_index,    0);
                    mhandler.sendMessage(msg);
                    //更新時間間隔為 2s 
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    cur_index++;  //放置在Thread.sleep(2000) ;防止mhandler處理消息的同步性,導致cur_index>=count_drawble
                }
            }
        }).start();
    }
    //通過handler來更新主界面  mgallery.setSelection(positon),選中第position的圖片,然後調用OnItemSelectedListener監聽改變圖像
    private Handler mhandler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == MSG_UPDATE) {
                Log.i(TAG, "cur_index"+ cur_index);
                mgallery.setSelection(msg.arg1);
                //UI Thread直接更改圖片 ,不利用Gallery.OnItemSelectedListener監聽更改
                //imgSwitcher.setBackgroundResource(imgAdapter.getResId(msg.arg1));
            }
        }
    };

    public void onDestroy() {
        super.onDestroy();
        isalive = false;
    }

    @Override
    public View makeView() {   //ImageSwitcher的ViewFactory方法
        // TODO Auto-generated method stub
        ImageView img = new ImageView(this);
        return img;
    }

    // 為Gallery控件提供適配器的類
    class ImageAdapter extends BaseAdapter {
        private Context mcontext;
        private ArrayList<Integer> residList = new ArrayList<Integer>(); // 通過放射機制保存所有圖片的id

        public ImageAdapter(Context context) {
            mcontext = context;
            // 反射的可重用性更好
            // R.id在R文件中本質上是一個類,我們通過這個R.id.class.getClass().getDeclaredFields()可以找到它的所有屬性
            Field[] residFields = R.drawable.class.getDeclaredFields();
            for (Field residField : residFields) {
                // 例如: public static final int icon=0x7f020000;
                // 它的Field表示為 : name= icon ; field.getInt() = 0x7f020000
                if (!"icon".equals(residField.getName())) {
                    int resid;
                    try {
                        resid = residField.getInt(null);// 找到該屬性的值
                        residList.add(resid);
                    } catch (IllegalArgumentException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }

        @Override
        public int getCount() {
            Log.e(TAG, " " + residList.size());
            return residList.size();
        }

        @Override
        public Object getItem(int position) {
            return residList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }
        //得到該圖片的res id
        public int getResId(int position) {
            return residList.get(position);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView img;
            if (convertView == null) {
                img = new ImageView(mcontext);
                img.setScaleType(ImageView.ScaleType.FIT_XY);
                img.setLayoutParams(new Gallery.LayoutParams(100, 100)); // 圖片顯示寬和長
                img.setImageResource(residList.get(position));
            } else {
                img = (ImageView) convertView;
            }
            return img;
        }

    }
}

主要的工程邏輯如上 ,由於采用了放射機制,直接添加圖片資源便可成功運行了。

本文源代碼地址為:http://download.csdn.net/detail/qinjuning/3888134

Android中Gallery和ImageSwitcher同步自動(滾動)播放圖片庫