【问题标题】:Android-Can't get listview item selectedAndroid-无法选择列表视图项目
【发布时间】:2011-12-11 10:46:40
【问题描述】:

我有一个带有两个 textviews 的自定义列表视图。如果我使用模拟器 d-pad,一切正常,行被选中,但如果我点击模拟器上的项目(或尝试在手机上选择),则没有任何内容被选中。

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>

代码:

    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;
                }
            });
        }

【问题讨论】:

    标签: java android listview


    【解决方案1】:

    为了使项目“可检查”,项目的顶视图应实现Checkable 接口。只有在这种情况下,您才会在ListView 中获得“已选中”/“未选中”状态。

    请注意,“可选择”和“可检查”项目具有不同的含义。在您的情况下,您的意思是“可检查”项目。不是“可选择的”。您需要“检查”您的项目,但ListView 确保在CHOICE_MODE_SINGLE 中一次最多检查一个项目。而“选定”项目是当前处于活动状态的项目(这主要用于可访问性需求)。

    您可以通过简单地将列表项布局中的LinearLayout 替换为CheckBox 视图来验证我所说的内容。 ListView 应该开始自动处理“已检查”状态。


    如果您想使用LinearLayout 并且仍然能够支持“已选中”/“未选中”状态,则需要实现扩展LinearLayout 并实现Checkable 接口的自定义布局。

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

    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();
        }
    }
    

    您的项目布局应如下所示:

    <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>
    

    并注意“drawable/checkakble_item”。它应该处理不同的状态。在我的示例中,它看起来像:

    <?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>
    

    drawable/item_presseddrawable/item_checkeddrawable/item_unchecked 是我的自定义可绘制对象。

    最后一点:在您的AdaptergetView() 中,您必须调用view.setClickable(false); 才能让ListView 处理可检查的状态,而不是CheckableLinearLayout

    【讨论】:

    • 您的代码正在运行,但它会检查多个项目,我想一次只检查一个。我试图检索当前的检查项目,但它不以这种方式工作: if(listaAll.size()>0) { if(listview.getCheckedItemPosition()>=0) { Clientid=listaAll.get(listview.getCheckedItemPosition() ).getClientID(); startActivity(new Intent(ClientiForm.this,ClientiDetaliiForm.class)); } else { Toast.makeText(ClientiForm.this,"Alegeti un client!", 10000).show(); } }
    • 确保您在适配器的getView() 中添加了view.setClickable(false)。或从CheckableLinearLayout 中删除setClickable(true)
    • 我在addresslist.xml的CheckableLinearLayout中添加了android:clickable="false",但是它检查了多个项目
    • Xml 的属性被我的实现覆盖(参见init())。你应该做我提到的两件事之一。
    猜你喜欢
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-04
    相关资源
    最近更新 更多