ListView CheckedTextView

时间:2013-05-07 15:27:22

标签: android listview checkedtextview

在我的Android应用程序中,我认为我的目标非常简单 - 生成已安装应用程序的列表并在每个旁边放置一个勾选框,作为“勾选到排除”列表。

要生成已安装的应用程序列表,我使用标准的Android示例代码,在片段here中进行演示。我不会重新发布所有内容以使这篇文章尽可能简洁。

性能非常糟糕,关于此主题的第一个问题是请求示例代码,LazyLoads应用程序图标。在images are being downloaded时,将LazyLoading图标实现为ListView似乎只是一个问题。由于Android在生成应用程序列表时不使用此方法,因此我想知道这是否过度杀伤?

当检查CheckedTextView并且视图在列表中回收further boxes become ticked down the list(在初始视图中)or they 'forget' they have been ticked时,问题就开始了。

为了解决这个问题,我必须保留对已勾选项目的引用并使用getView()中的following code

    // store CheckTextView's
    private static HashMap<Integer, CheckedTextView> mCheckedList = new HashMap<Integer, CheckedTextView>();
    // store state
    private static HashMap<Integer, Boolean> mIsChecked = new HashMap<Integer, Boolean>();

@Override
        public View getView(final int position, View convertView, final ViewGroup parent) {

            View view;

            if (convertView == null) {
                view = mInflater.inflate(R.layout.list_item_icon_text, parent, false);

            } else {
                view = convertView;

            }

            final AppEntry item = getItem(position);

            ((ImageView) view.findViewById(R.id.icon)).setImageDrawable(item.getIcon());

            CheckedTextView ctv = (CheckedTextView) view.findViewById(R.id.text1);
            ctv.setText(item.getLabel());

            // set current state
            if (mIsChecked.get(position) != null) {
                if (mIsChecked.get(position)) {
                    ctv.setChecked(true);
                }
            } else {
                ctv.setChecked(false);
            }

            ctv.setTag(position);
            mCheckedList.put(position, ctv);

            ctv.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View view) {

                    CheckedTextView ct = mCheckedList.get(view.getTag());

                    if (DE.BUG) {
                        MyLog.d("ct text: " + ct.getText().toString());
                    }

                    ct.toggle();

                    mIsChecked.put((Integer) view.getTag(), ct.isChecked());
                }

            });

            return view;

        }
    }

这很有效,但是由于为每个视图进行了刷新/回收所做的工作以及放置在每个项目上的OnClickListener(下面有更多内容),性能非常糟糕 - Eclipse还告诉我还有更多其他内容要改变:

  

使用新的SparseArray(...)代替更好   性能

我的困境并不止于此......为了帮助用户快速找到他们想要的应用程序,我实现了如下过滤器:

@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // Place an action bar item for searching.
    MenuItem item = menu.add("Search");
    item.setIcon(android.R.drawable.ic_menu_search);
    item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    View searchView = SearchViewCompat.newSearchView(getActivity());
    if (searchView != null) {
        SearchViewCompat.setOnQueryTextListener(searchView,
                new OnQueryTextListenerCompat() {
            @Override
            public boolean onQueryTextChange(String newText) {
                // Called when the action bar search text has changed.  Since this
                // is a simple array adapter, we can just have it do the filtering.
                mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
                mAdapter.getFilter().filter(mCurFilter);
                return true;
            }
        });
        item.setActionView(searchView);
    }
}

我假设当输入过滤器时,重新绘制ListView并且对位置的引用变得混乱?这导致框根据它们在显示器上的位置而被勾选。

我必须为上面的每个条目实现一个OnClickListener,因为我无法从onListItemClick获得对CheckedTextView的引用。以下是我的一些尝试:

@Override
public void onListItemClick(final ListView listView, final View view, final int position, final long id) {

    // View v = (View) listView.getChildAt(position);
    // CheckedTextView ctv = (CheckedTextView)
    // v.findViewById(R.id.text1);
    // ctv.toggle();

    // RelativeLayout r = (RelativeLayout) view;

    // CheckedTextView ctv = (CheckedTextView)
    // r.findViewById(R.id.text1);

    // CheckedTextView ctv = (CheckedTextView) view;

    // ((CheckedTextView)
    // listView.getItemAtPosition(position)).setChecked(!((CheckedTextView)
    // listView
    // .getItemAtPosition(position)).isChecked());

    // CheckedTextView ctv = (CheckedTextView) view.getTag(position);
    // ctv.toggle();

作为@CommonsWare replied in this topic,对findViewById(R.id.text1)的CheckedTextView引用不是我所追求的。

编辑 - XML布局

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:orientation="horizontal"
    android:paddingRight="6dip" >

    <CheckedTextView
        android:id="@+id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@+id/icon"
        android:checkMark="?android:attr/listChoiceIndicatorMultiple"
        android:paddingLeft="4dip"
        android:paddingTop="4dip"
        android:textStyle="bold"
        android:duplicateParentState="true" />

    <ImageView
        android:id="@+id/icon"
        android:layout_width="48dip"
        android:layout_height="48dip"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:paddingLeft="2dip" />

</RelativeLayout>

我准备放弃并使用单独的文本视图和复选框实现我自己的布局,但我不禁想到如果我这样做,我将重新发明轮子?我是否比应该做的更难!?

在理想的世界中:

  1. LazyLoad应用程序图标的已安装应用程序列表。
  2. 来自onListItemClick的实际CheckedTextView的引用。
  3. 存储和引用已检查项目的正确方法。
  4. 我希望有人可以提供帮助,我提前感谢你。

0 个答案:

没有答案