Android的 - 无法获取列表视图项选择 [英] Android-Can't get listview item selected

查看:138
本文介绍了Android的 - 无法获取列表视图项选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个textviews自定义列表视图。如果我使用仿真器D-垫,一切正常,该行被选中,但如果我在模拟器上的项目点击(或尽量选择在手机上)没有得到选择。

  addresslist.xml:
    < XML版本=1.0编码=UTF-8&GT?;
< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =FILL_PARENT机器人:layout_height =WRAP_CONTENT
    机器人:方向=横向的android:paddingBottom会=6DIP
    机器人:paddingTop =4dip>    < TextView的机器人:ID =@ + ID / DENUMIRE_CELL
        机器人:layout_width =50dp机器人:layout_height =WRAP_CONTENT
        机器人:layout_weight =1.03/>    < TextView的机器人:ID =@ + ID / ADRESA_CELL的android:layout_width =50dp
        机器人:layout_height =WRAP_CONTENT机器人:layout_weight =0.84/>
< / LinearLayout中>
clienti.xml:    < XML版本=1.0编码=UTF-8&GT?;
< TableLayout的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =FILL_PARENT机器人:layout_height =FILL_PARENT
    机器人:方向=垂直>    <的TableRow机器人:ID =@ + ID / tableRow1的android:layout_width =FILL_PARENT
        机器人:layout_height =WRAP_CONTENT>        <的LinearLayout机器人:方向=横向
            机器人:可聚焦=真正的机器人:focusableInTouchMode =真正的>
            < EditText上机器人:ID =@ + ID / editTextCauta
                机器人:layout_width =100dp机器人:layout_height =WRAP_CONTENT
                机器人:layout_weight =0.04/>            <按钮机器人:ID =@ + ID / buttonCauta的android:layout_width =70dp
                机器人:layout_height =WRAP_CONTENT机器人:文本=考塔/>
        < / LinearLayout中>    < /&的TableRow GT;
    <的TableRow机器人:ID =@ + ID / tableRowHeader
        机器人:layout_width =FILL_PARENT机器人:layout_height =WRAP_CONTENT
        机器人:背景=#000000>        <的LinearLayout机器人:方向=横向>
            < TextView的机器人:ID =@ + ID / textView1的android:layout_width =159dp
                机器人:layout_height =WRAP_CONTENT机器人:文本=Denumire
                机器人:textAppearance =机器人:ATTR / textAppearanceLarge
                机器人:文字颜色=#BBBBBB机器人:TEXTSIZE =15sp/>
            < TextView的机器人:ID =@ + ID / textView2的android:layout_width =159dp
                机器人:layout_height =WRAP_CONTENT机器人:文本=Adresa
                机器人:textAppearance =机器人:ATTR / textAppearanceLarge
                机器人:文字颜色=#BBBBBB机器人:TEXTSIZE =15sp/>        < / LinearLayout中>    < /&的TableRow GT;
    <的TableRow机器人:ID =@ + ID / tableRow2的android:layout_width =WRAP_CONTENT
        机器人:layout_height =WRAP_CONTENT机器人:baselineAligned =假>
        < ListView的机器人:ID =@ + ID / adresslist的android:layout_width =WRAP_CONTENT
            机器人:choiceMode =singleChoice机器人:layout_height =WRAP_CONTENT
            机器人:滚动条=横|纵/>    < /&的TableRow GT;
< / TableLayout>

code:

 公共无效adresalistBind()
        {
            列表视图=(ListView控件)findViewById(R.id.adresslist);            ArrayList的<&HashMap的LT;字符串,字符串>> MYLIST =新的ArrayList<&HashMap的LT;字符串,字符串>>();
            ArrayList的< ClientClass> clientlist =新的ArrayList< ClientClass>();            ClientClass.setClientContextForDB(本);            clientlist = ClientClass.ClientiGet();            listaAll = clientlist;
            HashMap的<字符串,字符串>地图;            的for(int i = 0; I< clientlist.size();我++)
            {
                地图=新的HashMap<字符串,字符串>();
                map.put(denumire,clientlist.get(ⅰ).getDenumire());
                map.put(adresa,clientlist.get(ⅰ).getAdresa());
                map.put(的clientid,将String.valueOf(clientlist.get(ⅰ).getClientID()));
                mylist.add(地图);
            }            SimpleAdapter mAdapter =新SimpleAdapter(这一点,MYLIST,R.layout.addresslist,
                        新的String [] {denumire,adresa},新的INT [] {R.id.DENUMIRE_CELL,R.id.ADRESA_CELL});
            listview.setAdapter(mAdapter);
            listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            listview.setSelection(1);
            listview.setOnItemSelectedListener(新OnItemSelectedListener()
            {
                公共无效onItemSelected(适配器视图<> adaptview,查看clickedview,INT位置,
                        长ID)
                {
                    //adaptview.setSelected(true);
                    listview.setSelection(位置);
                }                公共无效onNothingSelected(适配器视图<>为arg0)
                {
                }            });            listview.setOnItemClickListener(新OnItemClickListener()
            {
                公共无效onItemClick(适配器视图<> adaptview,查看ARG1,
                        INT位置,长ARG3)
                {
                    //adaptview.setSelected(true);
                   //查看rowview =(查看)adaptview.getChildAt(位置);
                   // rowview.setSelected(真);
                    listview.setSelection(位置);                    //Toast.makeText(ClientiForm.this,(字符串)listview.getItemAtPosition(位置)的ToString(),10000).show();
                }
            });            listview.setOnItemLongClickListener(新OnItemLongClickListener()
            {                公共布尔onItemLongClick(适配器视图<>为arg0,ARG1查看,
                        INT位置,长ARG3)
                {
                    listview.setSelection(位置);
                    openOptionsMenu();                    Toast.makeText(ClientiForm.this,(字符串)listview.getItemAtPosition(位置)的ToString(),10000).show();
                    返回false;
                }
            });
        }


解决方案

为了对项目是可检查,该项目的顶视图应该实施可勾选接口。只有在这种情况下,你会得到的ListView 中的检查/未选中状态。

需要注意的是可选和可检查的项目有不同的含义。在你的情况,你的意思是可检查项。不是选择。你需要你的项目是检查,但的ListView 确保最多有一个项目在 CHOICE_MODE_SINGLE 。而选择项是当前活跃的项目(这是主要用于无障碍需求)。

您可以验证我说的话,只需用复选框列表中的项目的布局视图替换的LinearLayout 。和的ListView 应该开始自动处理选中的状态。


如果你想使用的LinearLayout ,仍然能够支持检查/未登记状态,则需要实现扩展的LinearLayout 和农具可勾选接口。

下面是我这个实现的版本是:

 公共类CheckableLinearLayout扩展的LinearLayout实现可勾选{    私人布尔mChecked;    私有静态最终诠释[] = CHECKED_STATE_SET {
        android.R.attr.state_checked
    };    公共CheckableLinearLayout(上下文的背景下){
        这(背景下,NULL);
        在里面();
    }    公共CheckableLinearLayout(上下文的背景下,ATTRS的AttributeSet){
        超(背景下,ATTRS);
        在里面();
    }    私人无效的init(){
        setClickable(真);
    }    / ********************** /
    / **处理点击** /
    / ********************** /    @覆盖
    公共布尔performClick(){
        切换();
        返回super.performClick();
    }    @覆盖
    公共布尔onInterceptTouchEvent(MotionEvent EV){
        返回onTouchEvent(EV);
    }    / ************ /
    / ** **可勾选/
    / ************ /    公共无效切换(){
        setChecked(!mChecked);
    }    公共布尔器isChecked(){
        返回mChecked;
    }    公共无效setChecked(布尔选中){
        如果(mChecked!=选中){
            mChecked =检查;
            refreshDrawableState();
            setCheckedRecursive(这一点,选中);
        }
    }    私人无效setCheckedRecursive(ViewGroup中父母,布尔检查){
        诠释计数= parent.getChildCount();
        的for(int i = 0; I<计数;我++){
            视图V = parent.getChildAt(I)
            如果(V的instanceof可勾选){
                ((可勾选)V).setChecked(选中);
            }            如果(V的instanceof的ViewGroup){
                setCheckedRecursive((ViewGroup中)诉,检查);
            }
        }
    }    / ************ /
    / **绘制对象国** /
    / ************ /    @覆盖
    保护INT [] onCreateDrawableState(INT extraSpace){
        最终诠释[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        如果(器isChecked()){
            mergeDrawableStates(drawableState,CHECKED_STATE_SET);
        }
        返回drawableState;
    }    @覆盖
    保护无效drawableStateChanged(){
        super.drawableStateChanged();        可绘制可绘制=的getBackground();
        如果(绘!= NULL){
            INT [] = myDrawableState getDrawableState();
            drawable.setState(myDrawableState);
            无效();
        }
    }    / ************ /
    / **国家持续性** /
    / ************ /    静态类SavedState扩展BaseSavedState {
        布尔检查;        SavedState(Parcelable超级大国){
            超(超状态);
        }        私人SavedState(包裹中){
            超级(在);
            检查=(布尔)in.readValue(NULL);
        }        @覆盖
        公共无效writeToParcel(包裹出来,诠释标志){
            super.writeToParcel(出,旗);
            out.writeValue(选中);
        }        @覆盖
        公共字符串的toString(){
            回归CheckableLinearLayout.SavedState {
                    + Integer.toHexString(System.identityHash code(本))
                    +签=+ +检查};
        }        公共静态最终Parcelable.Creator< SavedState> CREATOR
                =新Parcelable.Creator< SavedState>(){
            公共SavedState createFromParcel(包裹中){
                返回新SavedState(中);
            }            公共SavedState [] newArray(INT大小){
                返回新SavedState【尺寸】;
            }
        };
    }    @覆盖
    公共Parcelable的onSaveInstanceState(){
        //强迫我们的祖先类保存其状态
        Parcelable超级大国= super.onSaveInstanceState();
        SavedState SS =新SavedState(覆);        ss.checked =器isChecked();
        返回SS;
    }    @覆盖
    公共无效onRestoreInstanceState(Parcelable状态){
        SavedState SS =(SavedState)状态;        super.onRestoreInstanceState(ss.getSuperState());
        setChecked(ss.checked);
        requestLayout();
    }
}

您项目的布局应该是这个样子:

 < com.your.pkg.CheckableLinearLayout的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:ID =@ + ID / linearLayout1
    机器人:layout_width =FILL_PARENT
    机器人:layout_height =WRAP_CONTENT
    机器人:背景=@绘制/ checkable_item>        <的TextView
            机器人:ID =@ + ID /名称
            机器人:layout_width =WRAP_CONTENT
            机器人:layout_height =WRAP_CONTENT
            机器人:文字=大文本
            机器人:textAppearance =:/>中的Andr​​oid ATTR / textAppearanceLarge?
< /com.your.pkg.CheckableLinearLayout>

和指出,绘/ checakble_item。它应该处理不同的状态。在我的例子,它看起来像:

 <?XML版本=1.0编码=UTF-8&GT?;
<选择的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android>    <项目的android:STATE_ pressed =真正的机器人:可绘制=@绘制/ ITEM_ pressed/>
    <项目的android:state_checked =真正的机器人:可绘制=@绘制/ item_checked/>
    <项目机器人:可绘制=@绘制/ item_unchecked/>< /选择>

其中,绘制/ ITEM_ pressed 绘制/ item_checked 绘制/ item_unchecked 是我的自定义绘制资源。

最后的那张字条:在你的适配器 getView()你必须调用 view.setClickable(假); 为可检查的状态由的ListView ,而不是由处理 CheckableLinearLayout

I have a custom listview with two textviews . If I use the emulator d-pad, everything works fine, the row is selected, but if I click on the item on the emulator (or try to select on the phone) nothing get selected.

addresslist.xml:
    <?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:paddingBottom="6dip"
    android:paddingTop="4dip">

    <TextView android:id="@+id/DENUMIRE_CELL"
        android:layout_width="50dp" android:layout_height="wrap_content"
        android:layout_weight="1.03" />

    <TextView android:id="@+id/ADRESA_CELL" android:layout_width="50dp"
        android:layout_height="wrap_content" android:layout_weight="0.84" />
</LinearLayout>
clienti.xml:

    <?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:orientation="vertical">

    <TableRow android:id="@+id/tableRow1" android:layout_width="fill_parent"
        android:layout_height="wrap_content">

        <LinearLayout android:orientation="horizontal"
            android:focusable="true" android:focusableInTouchMode="true">
            <EditText android:id="@+id/editTextCauta"
                android:layout_width="100dp" android:layout_height="wrap_content"
                android:layout_weight="0.04" />

            <Button android:id="@+id/buttonCauta" android:layout_width="70dp"
                android:layout_height="wrap_content" android:text="Cauta" />
        </LinearLayout>

    </TableRow>
    <TableRow android:id="@+id/tableRowHeader"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:background="#000000">

        <LinearLayout android:orientation="horizontal">
            <TextView android:id="@+id/textView1" android:layout_width="159dp"
                android:layout_height="wrap_content" android:text="Denumire"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:textColor="#BBBBBB" android:textSize="15sp" />
            <TextView android:id="@+id/textView2" android:layout_width="159dp"
                android:layout_height="wrap_content" android:text="Adresa"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:textColor="#BBBBBB" android:textSize="15sp" />

        </LinearLayout>

    </TableRow>
    <TableRow android:id="@+id/tableRow2" android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:baselineAligned="false">


        <ListView android:id="@+id/adresslist" android:layout_width="wrap_content"
            android:choiceMode="singleChoice" android:layout_height="wrap_content"
            android:scrollbars="horizontal|vertical" />

    </TableRow>


</TableLayout>

Code:

    public void adresalistBind()
        {
            listview = (ListView) findViewById(R.id.adresslist);

            ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
            ArrayList<ClientClass> clientlist=new ArrayList<ClientClass>();

            ClientClass.setClientContextForDB(this);

            clientlist=ClientClass.ClientiGet();

            listaAll=clientlist;


            HashMap<String, String> map;

            for(int i=0;i<clientlist.size();i++)
            {
                map = new HashMap<String, String>();
                map.put("denumire", clientlist.get(i).getDenumire());
                map.put("adresa", clientlist.get(i).getAdresa());
                map.put("clientid", String.valueOf(clientlist.get(i).getClientID()));
                mylist.add(map);
            }

            SimpleAdapter mAdapter = new SimpleAdapter(this, mylist, R.layout.addresslist,
                        new String[] {"denumire", "adresa"}, new int[] {R.id.DENUMIRE_CELL, R.id.ADRESA_CELL});
            listview.setAdapter(mAdapter);
            listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            listview.setSelection(1);
            listview.setOnItemSelectedListener(new OnItemSelectedListener() 
            {
                public void onItemSelected(AdapterView<?> adaptview, View clickedview, int position,
                        long id) 
                {
                    //adaptview.setSelected(true);
                    listview.setSelection(position);
                }

                public void onNothingSelected(AdapterView<?> arg0) 
                {
                }

            });

            listview.setOnItemClickListener(new OnItemClickListener() 
            {
                public void onItemClick(AdapterView<?> adaptview, View arg1,
                        int position, long arg3) 
                {
                    //adaptview.setSelected(true);
                   // View rowview = (View) adaptview.getChildAt(position);
                   // rowview.setSelected(true);
                    listview.setSelection(position);

                    //Toast.makeText(ClientiForm.this,  (String) listview.getItemAtPosition(position).toString(), 10000).show();
                }
            });

            listview.setOnItemLongClickListener(new OnItemLongClickListener() 
            {

                public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
                        int position, long arg3) 
                {
                    listview.setSelection(position);
                    openOptionsMenu();

                    Toast.makeText(ClientiForm.this,  (String) listview.getItemAtPosition(position).toString(), 10000).show();
                    return false;
                }
            });
        }

解决方案

In order for item to be "checkable", the top view of the item should implement Checkable interface. Only in this case you'll get "checked"/"unchecked" states within ListView.

Note that "selectable" and "checkable" items have different meanings. In your case you mean "checkable" item. Not "selectable". You need your items to be "checked", but ListView makes sure there is at most one item checked at a time in CHOICE_MODE_SINGLE. While "selected" item is item that is currently active (this is mostly used for accessibility needs).

You can verify what I said by simply replacing LinearLayout with CheckBox view in your list item's layout. And ListView should start handling "checked" states automatically.


If you want to use LinearLayout and still be able to support "checked"/"unchecked" states, you need to implement custom layout that extends LinearLayout and implements Checkable interface.

Here is what my version of this implementation is:

public class CheckableLinearLayout extends LinearLayout implements Checkable {

    private boolean mChecked;

    private static final int[] CHECKED_STATE_SET = {
        android.R.attr.state_checked
    };

    public CheckableLinearLayout(Context context) {
        this(context, null);
        init();
    }

    public CheckableLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {      
        setClickable(true);
    }

    /**********************/
    /**   Handle clicks  **/
    /**********************/

    @Override
    public boolean performClick() {
        toggle();
        return super.performClick();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return onTouchEvent(ev);
    }

    /**************************/
    /**      Checkable       **/
    /**************************/

    public void toggle() {
        setChecked(!mChecked);
    }

    public boolean isChecked() {
        return mChecked;
    }

    public void setChecked(boolean checked) {
        if (mChecked != checked) {
            mChecked = checked;
            refreshDrawableState();
            setCheckedRecursive(this, checked);
        }
    }  

    private void setCheckedRecursive(ViewGroup parent, boolean checked) {
        int count = parent.getChildCount();
        for(int i = 0; i < count; i++ ) { 
            View v = parent.getChildAt(i);
            if(v instanceof Checkable) {
                ((Checkable) v).setChecked(checked);
            }

            if(v instanceof ViewGroup) {
                setCheckedRecursive((ViewGroup)v, checked);
            }
        }
    }

    /**************************/
    /**   Drawable States    **/
    /**************************/

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        if (isChecked()) {
            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
        }
        return drawableState;
    }

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();

        Drawable drawable = getBackground();
        if (drawable != null) {
            int[] myDrawableState = getDrawableState();
            drawable.setState(myDrawableState);
            invalidate();
        }
    }

    /**************************/
    /**   State persistency  **/
    /**************************/

    static class SavedState extends BaseSavedState {
        boolean checked;

        SavedState(Parcelable superState) {
            super(superState);
        }

        private SavedState(Parcel in) {
            super(in);
            checked = (Boolean)in.readValue(null);
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeValue(checked);
        }

        @Override
        public String toString() {
            return "CheckableLinearLayout.SavedState{"
                    + Integer.toHexString(System.identityHashCode(this))
                    + " checked=" + checked + "}";
        }

        public static final Parcelable.Creator<SavedState> CREATOR
                = new Parcelable.Creator<SavedState>() {
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }

    @Override
    public Parcelable onSaveInstanceState() {
        // Force our ancestor class to save its state
        Parcelable superState = super.onSaveInstanceState();
        SavedState ss = new SavedState(superState);

        ss.checked = isChecked();
        return ss;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        SavedState ss = (SavedState) state;

        super.onRestoreInstanceState(ss.getSuperState());
        setChecked(ss.checked);
        requestLayout();
    }
}

Your item layout should look something like:

<com.your.pkg.CheckableLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" 
    android:background="@drawable/checkable_item">

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Large Text"
            android:textAppearance="?android:attr/textAppearanceLarge" />
</com.your.pkg.CheckableLinearLayout>

And note that "drawable/checakble_item". It should handle different states. In my example it looks like:

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

    <item android:state_pressed="true" android:drawable="@drawable/item_pressed" />
    <item android:state_checked="true" android:drawable="@drawable/item_checked"/>
    <item android:drawable="@drawable/item_unchecked" />

</selector>

Where drawable/item_pressed, drawable/item_checked and drawable/item_unchecked are my custom drawables.

The last note: in your Adapter's getView() you'll have to call view.setClickable(false); for checkable states to be handled by ListView and not by CheckableLinearLayout.

这篇关于Android的 - 无法获取列表视图项选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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