state_selected ListView项丢失在真实设备 [英] ListView item state_selected is lost on real device

查看:221
本文介绍了state_selected ListView项丢失在真实设备的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个三星手机上的​​一个简单的ListView的一个问题。

我编程方式创建一个新的ListView。该项目是简单的TextView。我把听众对我的列表视图:

  listView.setOnItemClickListener(新AdapterView.OnItemClickListener(){
        @覆盖
        公共无效onItemClick(适配器视图<>母公司,观景,INT位置,长的id){
            view.setSelected(真);
        }
    });

的TextView (即ListView控件的项目)使用 Col​​orStateList 的文字颜色(pressed - >绿色;选择 - >蓝;默认 - >红)

在模拟器,一切都很好:项红在默认情况下,当我preSS之一,它变成绿色,当我松开变成蓝色。如果我选择另一个项目:pviously选择了$ P $回到红色和新选择成为蓝色

在我的三星设备:项目默认情况下红色,当我preSS之一,它变成绿色,当我松开再次变成红色(即未选择)

<击>这似乎是在三星的ListView实现中的错误(这是一个自定义的实现难度大等无源$ C ​​$ C跟踪)。

修改:不是一个错误,但由于触控模式(见接受的答案链接)稍有不同的行为

你有没有对如何解决这个<击>错误/ 行为的任何想法?

附加约束:因为我收到的颜色只在运行时使用我不能使用的 XML选择

我的设备是三星GT-B5330,API 15(但我希望它发生在大多数的三星设备)

下面是完整的(编译)code

 进口android.R;
进口android.app.Activity;
进口android.content.res.ColorStateList;
进口android.database.DataSetObserver;
进口android.graphics.Color;
进口android.os.Bundle;
进口android.view.View;
进口android.view.ViewGroup;
进口android.widget.AdapterView;
进口android.widget.ListAdapter;
进口android.widget.ListView;
进口android.widget.RelativeLayout;
进口android.widget.TextView;公共类测试活动扩展了活动{公共无效的onCreate(捆绑savedInstanceState){
    super.onCreate(savedInstanceState);
    RelativeLayout的rootLayout =新的RelativeLayout(本);
    的setContentView(rootLayout);    //创建的ListView
    ListView控件的ListView =新的ListView(这一点);
    listView.setAdapter(新MyListAdapter());
    listView.setDivider(NULL);
    listView.setDividerHeight(0);
    listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    listView.setItemsCanFocus(假);
    listView.setOnItemClickListener(新AdapterView.OnItemClickListener(){
        @覆盖
        公共无效onItemClick(适配器视图&LT;&GT;母公司,观景,INT位置,长的id){
            view.setSelected(真);
        }
    });
    listView.setBackgroundColor(Color.WHITE);    //为定位的ListView
    RelativeLayout.LayoutParams LP =新RelativeLayout.LayoutParams(100,200);
    lp.setMargins(50,50,10,10);
    rootLayout.addView(ListView中,LP);
}私有类MyListAdapter实现ListAdapter {    @覆盖
    公共查看getView(INT位置,查看convertView,父母的ViewGroup){
        ColorStateList colorStateList =新ColorStateList(
                新的INT [] [] {
                        新的INT [] {R.attr.state_ pressed},
                        新的INT [] {} R.attr.state_selected,
                        新的INT [] { - R.attr.state_selected},
                },
                新的INT [] {
                        Color.GREEN,
                        Color.BLUE,
                        Color.RED});
        TextView中的TextView =新的TextView(parent.getContext());
        textView.setText(项目+位置);
        textView.setTextColor(colorStateList);
        返回的TextView;
    }    @覆盖
    公共布尔areAllItemsEnabled(){
        返回true;
    }    @覆盖
    公共布尔isEnabled(INT位置){
        返回true;
    }    @覆盖
    公共无效registerDataSetObserver(DataSetObserver观察者){
    }    @覆盖
    公共无效unregisterDataSetObserver(DataSetObserver观察者){
    }    @覆盖
    公众诠释的getCount(){
        返回10;
    }    @覆盖
    公共对象的getItem(INT位置){
        回归数据+位置;
    }    @覆盖
    众长getItemId(INT位置){
        返回的位置;
    }    @覆盖
    公共布尔hasStableIds(){
        返回true;
    }
    @覆盖
    公众诠释getItemViewType(INT位置){
        返回的位置;
    }    @覆盖
    公众诠释getViewTypeCount(){
        返回的getCount();
    }    @覆盖
    公共布尔的isEmpty(){
        返回的getCount()大于0;
    }
}
}


解决方案

我没有手头上有三星设备(Galaxy Nexus的这么想的计算,它具有普通Android和它的工作原理相当精细与你的例子),所以我不能测试我的假​​设,但似乎选择的ListView滴的项目状态已经释放之后。你可以用HierarchyViewer检查(使用罗曼盖伊的 ViewServer 如果你的手机是不是植根)。

这是很危险的依靠有选择,因为TouchMode的的触摸屏(见的 http://android-developers.blogspot.ru/2008/12/touch-mode.html )。在两句话:你没有选择的概念(或焦​​点,顺便说一句),当用户使用触摸屏进行交互。仿真器通常有D垫,因此它可能略有不同的行为。

所以,我对你的建议是使用 state_checked 而不是 state_selected 的。 Android有 CheckedTextView 这可能会有帮助。只需调用ListView的 setItemChecked 。该解决方案还具有保持配置更改和全自动取消选中$ P $的检查项目位置pviously检查项目,当其他项目pressed的良好特性(如 CHOICE_MODE_SINGLE 时)

如果这是不能接受的,您需要使用 state_selected 坚持,那么你可以换你的TextView到LinearLayout中,应该从$消失p $ pvent选择。但是不要忘记,ListView控件重用其他列表项相同的观点,当它熄灭屏幕,所以你需要追踪您的适配器选择状态正确设置它。

I have a problem with a simple ListView on a Samsung phone.

I create a new ListView programmatically. The items are simple TextView. I put a listener on my list view:

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            view.setSelected(true);
        }
    });

The TextView (i.e. items of listView) use a ColorStateList as textColor (pressed-->Green ; selected-->Blue ; default-->Red).

On the emulator, everything is fine : items are red by default , when I press one it become green, and when I release it become blue. If I select another item : the previously selected go back to red and the newly selected became blue.

On my Samsung device : items are red by default , when I press one it become green, and when I release it become red again (i.e. not selected).

It seems to be a bug in the Samsung ListView implementation (it's a custom implementation and so difficult to trace without source code).

EDIT: not a bug but a slightly different behavior because of touch mode (see link in accepted answer)

Do you have any ideas on how to workaround this bug/behavior?

Additional constraint: I can't use an xml selector because I receive the color to use only at runtime.

My device is a Samsung GT-B5330 , API 15. (but I expect it occurs on most Samsung devices)

Here is the complete (compilable) code

import android.R;
import android.app.Activity;
import android.content.res.ColorStateList;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class TestActivity extends Activity {

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    RelativeLayout rootLayout = new RelativeLayout(this);
    setContentView(rootLayout);

    //create listView
    ListView listView = new ListView(this);
    listView.setAdapter(new MyListAdapter());
    listView.setDivider(null);
    listView.setDividerHeight(0);
    listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    listView.setItemsCanFocus(false);
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            view.setSelected(true);
        }
    });
    listView.setBackgroundColor(Color.WHITE);

    //positionning listView
    RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(100,200);
    lp.setMargins(50,50,10,10);
    rootLayout.addView(listView, lp);
}



private class MyListAdapter implements ListAdapter{

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ColorStateList colorStateList = new ColorStateList(
                new int[][]{
                        new int[]{R.attr.state_pressed},
                        new int[]{R.attr.state_selected},
                        new int[]{-R.attr.state_selected},
                },
                new int[]{
                        Color.GREEN,
                        Color.BLUE,
                        Color.RED});
        TextView textView = new TextView(parent.getContext());
        textView.setText("Item " + position);
        textView.setTextColor(colorStateList);
        return textView;
    }

    @Override
    public boolean areAllItemsEnabled() {
        return true;
    }

    @Override
    public boolean isEnabled(int position) {
        return true;
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
    }

    @Override
    public int getCount() {
        return 10;
    }

    @Override
    public Object getItem(int position) {
        return "data "+position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }


    @Override
    public int getItemViewType(int position) {
        return position;
    }

    @Override
    public int getViewTypeCount() {
        return getCount();
    }

    @Override
    public boolean isEmpty() {
        return getCount()>0;
    }
}
}

解决方案

I don't have a samsung device on hand (Galaxy Nexus dosen't count, it has plain Android and it works quite fine with your example) so I cannot test my assumptions but it seems that ListView drops selected state of the item after it has been released. You can check it with HierarchyViewer (use Romain Guy's ViewServer if your phone isn't rooted).

It is dangerous to rely on selection having a touchscreen because of TouchMode (see http://android-developers.blogspot.ru/2008/12/touch-mode.html). In two words: you don't have a concept of selection (or focus, btw) when a user is interacting with a touchscreen. Emulator usually has D-pad so it may have slightly different behavior.

So my suggestion for you is to use state_checked instead of state_selected. Android has CheckedTextView that may help. Just call ListView's setItemChecked. This solution also has nice properties of keeping checked item position between configuration changes and automatical unchecking previously checked item when other item is pressed (if CHOICE_MODE_SINGLE is used).

If it is not acceptable and you need to stick with state_selected then you may wrap your TextView into LinearLayout, it should prevent selection from disappearing. But don't forget that ListView reuses the same view for other list items when it goes out of screen, so you need to track selection state in your adapter to properly set it.

这篇关于state_selected ListView项丢失在真实设备的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆