[置顶] 关于点击ListView使其中的子控件的text文字变色的问题

ListView中想让text变色是一个比较棘手的问题,事实上有很多人都遇到了问题,可是能解决的方案不多,这个帖子旨在帮助大家

解决这个问题,好,让我们通过两种方式来看看。


1.用selector和setTextColor的方式

这是一种执行效率比较高的方法

一,在listview的adapter xml中找到要变色的控件,用setTextColor或者style来改变颜色,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent" android:layout_height="wrap_content"
	android:orientation="horizontal" android:paddingLeft="5dip"
	android:descendantFocusability="blocksDescendants"
	 android:background="@drawable/listview_state_bg"
	android:paddingRight="5dip">

	<ImageButton android:id="@+id/headphoto" android:layout_width="45dip"
		android:layout_height="45dip" android:layout_marginTop="10dip"
		android:layout_marginLeft="10dip" android:focusable="false"
		android:background="@drawable/recfriend_pic_box" android:scaleType="fitCenter"
		android:src="@drawable/pic_bg" android:layout_marginBottom="10dip"/>

	<LinearLayout android:layout_width="fill_parent"
	    android:id="@+id/text_layout"
		android:layout_height="wrap_content" android:orientation="vertical"
		android:paddingLeft="10dip" android:paddingTop="8dip" android:focusable="false"
		android:layout_weight="1">

		<LinearLayout android:orientation="horizontal" android:focusable="false"
			android:layout_width="fill_parent" android:layout_height="wrap_content">

			<TextView android:id="@+id/name" android:layout_width="wrap_content"
				android:layout_height="wrap_content" android:textSize="16dip"
				style="@style/textview_title"	android:focusable="false"/>

			<ImageView android:id="@+id/pageicon" android:layout_width="wrap_content"
				android:layout_height="wrap_content" android:src="@drawable/page_icon_new"
				android:focusable="false"
				android:visibility="gone"/>

			<LinearLayout android:layout_width="wrap_content" android:focusable="false"
				android:layout_height="wrap_content" android:layout_weight="1"/>

		</LinearLayout>

		<TextView android:id="@+id/text1" android:layout_width="wrap_content" 
		    android:layout_marginTop="4dip" android:focusable="false"
			android:layout_height="wrap_content" android:textColor="@drawable/rec_button_color"
			android:textSize="14sp" android:visibility="gone"/>

		<TextView android:id="@+id/text2" android:layout_width="wrap_content"
		    android:focusable="false"
			android:layout_height="wrap_content" android:textColor="@drawable/rec_button_color"
			android:textSize="14sp" android:visibility="gone"/>
	

	</LinearLayout>
	
	<CheckBox android:id="@+id/checkbox" android:layout_width="wrap_content"
	    android:layout_height="wrap_content" android:layout_marginRight="5dip" 
	    android:focusable="false" android:button="@drawable/checkbox"
   	    android:layout_gravity="center_vertical"/>
	<ImageButton android:id="@+id/arrow" android:layout_width="wrap_content"
	    android:focusable="false"
		android:layout_height="wrap_content" android:background="@drawable/profile_icon_arrow"
		android:layout_gravity="center_vertical" android:layout_marginRight="5dip" 
		android:visibility="gone"/>
</LinearLayout>


特别注意的是,在你的adapter的最外层linearLayout里有一句话

	android:descendantFocusability="blocksDescendants"

是必须的,否则无法实现点击变色,它的功能是覆盖子控件的onclick事件。解释如下:

android:descendantFocusability

Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.

Must be one of the following constant values.

Constant Value Description
beforeDescendants 0 The ViewGroup will get focus before any of its descendants.
afterDescendants 1 The ViewGroup will get focus only if none of its descendants want it.
blocksDescendants 2 The ViewGroup will block its descendants from receiving focus.


其中的ID name,text1,text2都是需要点击变色的textview,分别用了style和textColor,其中rec_button_color.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_pressed="false" android:color="@color/profile_color"/>
    <item android:state_pressed="true" android:color="@color/white"/>
</selector>

注意要写在drawable文件夹下。

style(注意不是android:style)指向的textview_title写在values/style.xml中,如下:

<?xml version= "1.0" encoding= "utf-8"?>
<resources xmlns:adnroid="http://schemas.android.com/apk/res/android">
    <style name="textview_title">
		  <item name="android:textColor">@color/title_color</item> 
		  <item name="android:duplicateParentState">true</item> 
 	</style>

	
</resources>

其中的@color/title_color是写在res/color文件夹下的一个xml,与rec_button_color.xml相似:

<?xml version="1.0" encoding="utf-8"?>

<selector xmlns:android="http://schemas.android.com/apk/res/android">

  <item android:state_pressed="true" android:color="@color/white" /> 
  <item android:color="@color/black" /> 

</selector>


二,至此xml文件的设置就结束了,正常情况下就可以实现点击变色了,可问题往往在这里出现了,

有时候我们的listeview item需要有点击事件,如在ListView Adapter类里的getView()中实现如下功能:

		view.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {				
					if(holder.checkbox.isChecked()){
						holder.checkbox.setChecked(false);
					}else {
						holder.checkbox.setChecked(true);
					} 
					
				} 
			}
		});

即实现点击item实现其中的checkbox选中,如果加入这段代码,则点击变色不能成功,因为我们的外部view把内部控件的点击事件都覆盖了,不会执行

到子控件的点击变色部分。

所以需要有变通的方案,即在包含Listview的Activity中给Listview加入setOnItemClickListener,而不通过view.setOnClickListener:

		mListView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				RecommendFriendsAdapter.ViewHolder holder = (RecommendFriendsAdapter.ViewHolder)view.getTag();
				if(holder.checkbox!= null){
					if(holder.checkbox.isChecked()){
						holder.checkbox.setChecked(false);
					}else {
						holder.checkbox.setChecked(true);
					} 
				}
			}
			
		});
这样即实现了点击变色,也实现了点击需要的其它功能。

如果需要在点击父控件时还要让checkbox变色,则在最上部分的checkbox一项里加入

android:button="@drawable/checkbox"
其中checkbox.xml为:

<?xml version= "1.0" encoding= "UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/btn_checkbox_normal" android:state_checked="false" android:state_pressed="false"/>
    <item android:drawable="@drawable/btn_checkbox_pressed" android:state_checked="false" android:state_pressed="true"/>
    <item android:drawable="@drawable/bth_checkbox_normal" android:state_checked="true" android:state_pressed="false"/>
    <item android:drawable="@drawable/bth_checkbox_pressed" android:state_checked="true" android:state_pressed="true"/>

</selector>
这样就实现了选中变色。

累死lz了,这个方案前前后后搞了至少半个月,因为后面的setOnClickListener问题一直阻塞,现在终于搞出来了!

希望对自己和大家都有帮助。

2. 下面的方法是之前没有找到上面方法的替代方法,用于一些极端情况下能实现效果,

它的缺点是在滑动的时候也会有时触发点击效果,从而使得滑动变得比较卡,不过作为临时方法也可以接受,

同等情况优先使用第一种方法。

在adapter的getView()方法里加入下面的话

		view.setOnTouchListener(new View.OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				Log.d("meng", "action + "+event.getAction());
				if(event.getAction() == 0){
					view.setBackgroundColor(Color.parseColor("#2cb1e1"));
					holder.name.setTextColor(Color.WHITE);
					holder.text1.setTextColor(Color.WHITE);
					holder.text2.setTextColor(Color.WHITE);
				}else if(event.getAction() == 2){
					view.setBackgroundColor(Color.parseColor("#2cb1e1"));
					holder.name.setTextColor(Color.WHITE);
					holder.text1.setTextColor(Color.WHITE);
					holder.text2.setTextColor(Color.WHITE);
				}else if(event.getAction() == 3){
					view.setBackgroundColor(Color.TRANSPARENT);
					holder.name.setTextColor(Color.BLACK);
					holder.text1.setTextColor(R.color.profile_color);
					holder.text2.setTextColor(R.color.profile_color);
				}else if(event.getAction() == 1){
					view.setBackgroundColor(Color.TRANSPARENT);
					holder.name.setTextColor(Color.BLACK);
					holder.text1.setTextColor(R.color.profile_color);
					holder.text2.setTextColor(R.color.profile_color);
				}else{
					Log.d("meng", "else + "+event.getAction());
					view.setBackgroundColor(Color.TRANSPARENT);
					holder.name.setTextColor(Color.BLACK);
					holder.text1.setTextColor(R.color.profile_color);
					holder.text2.setTextColor(R.color.profile_color);
				}
				
				return false;
			}


注意:如果要同时换背景,最好用color值,用图片会产生布局混乱的问题,而且必须用

view.setBackgroundColor(Color.parseColor("#2cb1e1"));

不要用你自己定义的id R.color.xxx,这样颜色会变的,而且不能用

view.setBackgroundResource(R.color.item_click_color); 

因为个别手机尤其是4.0系统的手机会出现点击一会就不变色的bug!

else其实可有可无了,是为了保险加入的。



参考链接http://gundumw100.iteye.com/blog/1169065


ps:今天发现有网站转了我的文章,但不标明作者,甚至都不写转,希望大家转载的时候

至少写上个转自mengweiqi33,谢谢!

你可能感兴趣的:([置顶] 关于点击ListView使其中的子控件的text文字变色的问题)