我在工作中发现:触碰模式下的listview项无法被选中,所谓选中,意思是点击选中该项后,背景长期高亮。
在模拟器上测试时,可以使用鼠标滑轮滚动选中,这会调用onItemSelected()方法,在这里可以设置选中项高亮。
在真机上,由于没有滑轮,只能用手指点击选中,但是点击时,不会有选中后高亮的效果(注意:选中后高亮不是指点击选中那一下高亮,而是点击后长期高亮)。
或许你会想到使用selector背景选择器来设置:
<?xml version="1.0" encoding="utf-8" ?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 默认时的背景图片--> <item android:drawable="@drawable/pic1" /> <!-- 没有焦点时的背景图片--> <item android:state_window_focused="false" android:drawable="@drawable/pic1" /> <!-- 非触摸模式下获得焦点并单击时的背景图片--> <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/pic2" /> <!-- 触摸模式下单击时的背景图片--> <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/pic3" /> <!--选中时的图片背景--> <item android:state_selected="true" android:drawable="@drawable/pic4" /> <!--获得焦点时的图片背景--> <item android:state_focused="true" android:drawable="@drawable/pic5" /> </selector>
悲剧的是:我无法使用selector实现我想要的那种选中后长期高亮的状态
于是我只能在java代码中寻求思路了
下面的代码实现listview单选模式下点击后背景图片长期高亮
package org.yaoming.listview; import org.yaoming.util.Common; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; public class Listview_selectorActivity extends Activity implements OnItemClickListener { private String[] arrays; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); arrays = new String[] {"a","b","c","d","e"}; //使用SharedPreferences是为了每次点击退出时都保存之前选中的项,以后一打开时就可以看到以前的选择 SharedPreferences sp = getSharedPreferences("testListview", 0); Common.SELECTED = sp.getInt("selected", Common.SELECTED); ListView listview = (ListView) findViewById(R.id.listView1); listview.setAdapter(new MyAdapter(this)); listview.setOnItemClickListener(this); } public class MyAdapter extends BaseAdapter{ Context context; public class ViewHolder{ TextView tv; ImageView iv; } public MyAdapter(Context context){ this.context = context; } @Override public int getCount() { // TODO Auto-generated method stub return arrays.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return position; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { //通过日志测试,原来每次点击listview的每一项,这里都会运行 //通过查看源码,原来是getItemAtPosition()中getAdapter()搞的鬼 Log.i("listview", "zhixingguo "); LinearLayout layout; ViewHolder viewholder; if(null == convertView){ layout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.item, null); viewholder = new ViewHolder(); viewholder.tv = (TextView) layout.findViewById(R.id.textView2); viewholder.iv = (ImageView) layout.findViewById(R.id.imageView1); convertView = layout; layout.setTag(viewholder); }else{ layout = (LinearLayout) convertView; viewholder = (ViewHolder) layout.getTag(); } viewholder.tv.setText(arrays[position]); //在这里加个判断,若为选中项,则改变背景图片和背景色 if(Common.SELECTED == position){ viewholder.iv.setBackgroundResource(R.drawable.asi); layout.setBackgroundResource(R.color.blue); }else { viewholder.iv.setBackgroundResource(R.drawable.icon); layout.setBackgroundResource(R.color.transparent); } return convertView; } } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //如果在这里简单地通过findviewbyid()改变背景图片,点击时会出现图片乱显示的情况 // ImageView iv = (ImageView) view.findViewById(R.id.imageView1); // iv.setImageResource(R.drawable.asi); //改变SELECTED的值,并在getview里判断加载的位置是否为选中的位置 Common.SELECTED = position; } }
还有一个自定义的util类
package org.yaoming.util; public class Common { public static int SELECTED = -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" /> <ListView android:id="@+id/listView1" android:choiceMode="singleChoice" android:cacheColorHint="#00000000" android:layout_height="wrap_content" android:layout_width="match_parent"></ListView> </LinearLayout>
listview的item布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:text="TextView" android:id="@+id/textView2" android:textSize="30sp" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView> <ImageView android:src="@drawable/icon" android:layout_width="wrap_content" android:id="@+id/imageView1" android:layout_height="wrap_content"></ImageView> </LinearLayout>
不使用selector,直接在java代码里设置。在onItemClick的时候获得position,并在getview判断是否为选中项,设置背景颜色高亮,记得布局文件中listview要设置成singleChoiceMode。
值得注意的是,onItemClick会触发getItemAtPosition方法
/** * Callback method to be invoked when an item in this AdapterView has * been clicked. * <p> * Implementers can call getItemAtPosition(position) if they need * to access the data associated with the selected item. * * @param parent The AdapterView where the click happened. * @param view The view within the AdapterView that was clicked (this * will be a view provided by the adapter) * @param position The position of the view in the adapter. * @param id The row id of the item that was clicked. */ void onItemClick(AdapterView<?> parent, View view, int position, long id); }
而getItemAtPosition又会调用getAdapter方法,就相当于重新刷新一次ui中的listview
/** * Gets the data associated with the specified position in the list. * * @param position Which data to get * @return The data associated with the specified position in the list */ public Object getItemAtPosition(int position) { T adapter = getAdapter(); return (adapter == null || position < 0) ? null : adapter.getItem(position); }
实现效果如下:
第一次写技术博客,多有差池请多多指教,如有说不清楚的地方,请赐教。
下面是源码下载地址
http://download.csdn.net/detail/iamkila/4034770