天天看点

Android 中如何才能让 StackView 的 OnItemSelectedListener 侦听器响应选中事件

  StackView 组件能以堆叠方式显示一组图片,其滑动手指查看图片的操作方便而且直观。我们在切图的时候或许还希望更新一些文字描述等相关信息,这时你会发现 StackView 已经提供了一个 setOnItemSelectedListener() 方法,可以设置 OnItemSelectedListener() 侦听器以便在图片切换后执行后续工作。不过先别高兴得太早,测试时你会发现 OnItemSelectedListener() 懒洋洋的什么都没做。

  度娘了一下,有关 StackView 组件的文章极少(莫非少有人用?),只看到有说法是 Android 并没为 StackView 组件提供 OnItemSelectedListener() 的实现,解决方案却没有找到;或者只是建议设置另一监听器 setOnItemClickListener(),而该监听器只有在点击时才会响应——难道要我告诉用户,你滑动手指切换图片后,还得傻傻地再点击一次,所看到的才是相应的文本信息?

  翻墙,Google 帮忙在国外网站中找到了一个解决方案:通过扩展 StackView 并“激活”其 OnItemSelectedListener 侦听器即可。不过在实测中,当图片在最后一张和第一张之间循环切换时,应用会异常退出。跟踪发现重载方法 setDisplayedChild(int whichChild) 中接收到的 whichChild 本身应该是表示图片组中各图片序号的(相当于数组下标值),而该值在增长到最后一张图片时并不会停下来归零,而是继续增长,这样导致传给 onItemSelected 的参数出现了“越界”的错误,最终导致应用崩溃。查到原因后对症下药,问题自然解决。以下是扩展 StackView 的源码,在项目中创建该类后直接使用即可——

StackViewAdv.java

package com.yunbing.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.StackView;
public class StackViewAdv extends StackView
{
    public StackViewAdv(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }
    public StackViewAdv(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }
    @Override
    public void setDisplayedChild(int whichChild)
    {
    	Log.d("test", "传入的 whichChild = " + whichChild);
    	// 当图片组由最后一张循环切换到第一张时,所获取的 whichChild 将发生越界(这里变为5);
    	// 当图片组由第一张倒循环切换到最后一张时,whichChild==-1,同样发生越界,因此做如下处理
    	int index = whichChild;
    	int countImg = 5;   //图片的总数,实际项目时暂时可考虑用全局变量
		if (index < 0) index = countImg-1; // 由第一张倒循环切换到最后一张时,whichChild==-1
		index = index % countImg;  //循环序号
		
		// “激活” OnItemSelectedListener 侦听器
        this.getOnItemSelectedListener().onItemSelected(this, null, index, -1);
        super.setDisplayedChild(whichChild);
    }
}
           

以下是项目应用示例——

布局文件:main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent">
	
	<com.yunbing.ui.StackViewAdv
		android:id="@+id/mStackView"
		android:layout_width="wrap_content"
		android:layout_height="400dp"
		android:layout_centerInParent="true"
		android:loopViews="true" />
	
	<TextView 
	    android:id="@+id/tv_text"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:textSize="16sp"
	    android:layout_marginBottom="20dp"
	    android:layout_marginLeft="20dp"
	    android:layout_alignParentBottom="true"/>
	
</RelativeLayout>
           

程序源文件:StackViewTest.java

package com.yunbing.ui;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.SimpleAdapter;
import android.widget.TextView;
/**
 * Description:
 * <br/>site: <a href="http://www.yunbing.com" target="_blank" rel="external nofollow" >云冰工作室</a>
 * <br/>Copyright (C), 2015, Yunbing
 * <br/>This program is protected by copyright Yunbing.
 * <br/>Program Name: 自定义StackView
 * <br/>Date: 2015-02-11
 * @author  Yunbing [email protected]
 * @version  1.0
 */
public class StackViewTest extends Activity
{
	StackViewAdv stackView;
	TextView tvAbout;
	
	int[] imageIds = new int[]
	{
		R.drawable.img01, R.drawable.img02, R.drawable.img03
		, R.drawable.img04, R.drawable.img05};	
		
	//图片组的相应文本
	String[] strAbouts = {"1. 人造卫星正在展开太阳帆", "2. 行星撞击地球的美丽瞬间", 
			"3. 壮观的九大行星", "4. 木星和他的小伙伴", "5. 太阳系的演变-yunbing.com"};
	
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		stackView = (StackViewAdv) findViewById(R.id.mStackView);
		tvAbout = (TextView) findViewById(R.id.tv_text);
		// 创建一个List对象,List对象的元素是Map
		List<Map<String, Object>> listItems = 
				new ArrayList<Map<String, Object>>();
		for (int i = 0; i < imageIds.length; i++)
		{
			Map<String, Object> listItem = new HashMap<String, Object>();
			listItem.put("image", imageIds[i]);
			listItems.add(listItem);
		}
		
		// 创建一个SimpleAdapter
		SimpleAdapter simpleAdapter = new SimpleAdapter(this,
				listItems
				// 使用/layout/cell.xml文件作为界面布局
				, R.layout.cell, new String[] { "image" },
				new int[] { R.id.image1 });		
		stackView.setAdapter(simpleAdapter);
		//图片切换时更新文本内容
		stackView.setOnItemSelectedListener(new OnItemSelectedListener() {
			@Override
			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				// 设置文本
				tvAbout.setText(strAbouts[arg2]);
			}
			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				// TODO Auto-generated method stub
				
			}
		});
		
		stackView.setSelection(0);
	}	
	
}
           

本文的示例源码下载地址: http://download.csdn.net/detail/midong2000/8459751