Получение выбранного вида из ListView - PullRequest
1 голос
/ 03 марта 2012

Я использую CursorAdapter для обработки ListActivity:

public class Mclass extends ListActivity{
...
TheAdapter mAdapter;
public static HashMap<Long, Boolean> shown = new HashMap<Long, Boolean>();
...

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
         Boolean tmp = shown.get(id); 
        if (tmp == null) { // if null we don't have this key in the hashmap so we added with the value true
            shown.put(id, true);
        } else {
            shown.put(id, !tmp.booleanValue()); // if the value exists in the map then inverse it's value
        }
    mAdapter.notifyDataSetChanged();
         }

}

и мой класс адаптера, который расширяет CursorAdapter и переопределяет bindView:

@Override
public void bindView(View view, Context context, Cursor cursor) {
    String listText= cursor
            .getString(cursor
                    .getColumnIndexOrThrow(DataHandler.MY_TEXT));

long id = cursor.getLong(cursor.getColumnIndexOrThrow(DataHandler.ROW_ID)); 
    if (Mclass.shown.get(id) != null) {
        TextView m_text = (TextView) view
                .findViewById(R.id.my_text);
        if (m_text != null) {
            m_text.setVisibility(Mclass.shown.get(id)? View.VISIBLE:
                     View.GONE);

            if (m_text.isShown())
                m_text.setText("STRING");
   }
}

Расположение моего элемента списка определено в XML-файле list_item.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#DDDDDD"
android:orientation="horizontal" >

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/my_image"
        android:layout_width="wrap_content"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:paddingRight="1dip"
        android:paddingTop="1dip"
</LinearLayout>

/*
 *I want to toggle this text view's visibility
 */
<TextView
    android:id="@+id/my_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="gone"//VISIBILITY defined here
    android:paddingBottom="2dip"
    android:paddingLeft="4dip"
    android:paddingRight="4dip"
    android:paddingTop="5dip" />
 </LinearLayout>

Как я могу переключить видимость TextView в моем макете в onListItemClick? Я пробовал:

TextView mTextView = (TextView) v.findViewById(R.id.my_text);
mTextView.setVisibility(mTextView.isShown()? View.GONE: View.VISIBLE);
mAdapter.notifyDataSetChanged();

но, похоже, он выбирает, какие элементы списка переключать случайным образом, независимо от того, что я нажимаю.

Ответы [ 3 ]

3 голосов
/ 03 марта 2012

Вам нужно будет хранить идентификаторы строк, которые вы будете скрывать.Вы можете создать поле в своей деятельности для хранения этих идентификаторов:

HashMap<Long, Boolean> positionHide = new HashMap<Long, Boolean>();

, где ключ - это длинный идентификатор строки, а логический объект представляет состояние TextView (false - он пропалПравда, это видно).В onListItemClick() добавьте идентификаторы выбранных строк в это поле:

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
         Boolean tmp = positionHide.get(id); 
        if (tmp == null) { // if null we don't have this key in the hashmap so we added with the value true
            status.put(id, true);
        } else {
            status.put(id, !tmp.booleanValue()); // if the value exists in the map then inverse it's value
        }
        mAdapter.notifyDataSetChanged();
    }

также измените метод bindView():

@Override
public void bindView(View view, Context context, Cursor cursor) {
    String listText = cursor.getString(cursor
            .getColumnIndexOrThrow(DataHandler.MY_TEXT));
    long pos = cursor.getLong(cursor.getColumnIndex(DataHandler.ID)); // DataHandler.ID will point to the column _id
TextView m_text = (TextView) view.findViewById(R.id.my_text);

    if(status.get(pos) == null) {
//id is not yet in the hashmap so the value is 
//by default false, the TextView is invisible
    m_text.setVisibility(View.GONE);

    } else {
        // we have the value in the
        // Hashmap so see what it is and set the
    // textview visibility from this value

        if (tmp.booleanValue()) {
          m_text.setVisibility(View.VISIBLE);
             } else {
                 m_text.setVisibility(View.GONE);
                   }
          }
    if (m_text != null)
     m_text.setText(listText);  

}

Чтобы это работало, вам понадобитсяиметь в своей базе данных столбец _id INTEGER PRIMARY KEY AUTOINCREMENT (а также добавленный в запрос).

1 голос
/ 03 марта 2012

Ну, вы не должны использовать ListView для любого активного просмотра, попробуйте вместо этого использовать TableLayout или LinearLayout. Посмотрите на эту запись в блоге , чтобы узнать больше об этом, однако это для CheckBoxes, но верно для любого активного просмотра.

1 голос
/ 03 марта 2012

Вы проблема в том, что представления повторно используются в представлении списка. Это означает, что даже если у вас есть список, состоящий из 100 элементов, будет только 10 или около того экземпляров просмотра (в зависимости от того, сколько можно разместить на экране). Если вы видите, что метод bindView использует представление для повторного использования в качестве параметра.

То, что вы сделали, это вид, который отображает, например, 23-й элемент в списке, и скрывает текстовое поле. Когда 23-й элемент прокручивается за пределы экрана, его представление используется повторно, но только данные 33-го элемента заменяются только значениями, видимость и другие параметры, которые вы задаете для представления, которое вы повторно используете, остаются прежними.

Что вам нужно сделать, это добавить логическое состояние для всех элементов списка и в bindView адаптера переключить видимость текстовых полей в соответствии с текущим требуемым состоянием элемента.

Другая важная вещь, которую нужно увидеть, это то, что при нажатии на элемент метод bindView не вызывается. Таким образом, вы должны также переключить видимость в методе onClick, чтобы сделать изменение мгновенным. Если вы пропустите это, внешний вид представления изменится только после того, как элемент будет прокручен и снова прокручен - тогда bindView проверяет булевость видимости.

Было бы более удобно уведомлять DataSetObservers об изменении в «данных» и позволять ListView вызывать bindView для всех видимых элементов, но он также более ресурсоемкий.

HashMap<Long, Boolean> positionHide = new HashMap<Long, Boolean>();
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
         Boolean tmp = positionHide.get(id); 
        if (tmp == null) { // if null we don't have this key in the hashmap so we added with the value true
            positionHide.put(id, true);
            tmp = true;
        } else {
                        tmp = !tmp.booleanValue();
            positionHide.put(id, !tmp.booleanValue()); // if the value exists in the map then inverse it's value
        }
        // You should also hide the text view, because bindView will not be called until the list item is scrolled out and in again
                TextView m_text = (TextView) view.findViewById(R.id.my_text);
        if (m_text != null) {
              if(tmp) {
                            // We should hide the text view
                            m_text.setVisibility(View.GONE);
                  } else {
                        // We should display the text view
                            m_text.setVisibility(View.VISIBLE);
                  }
        } 
    }


@Override
public void bindView(View view, Context context, Cursor cursor) {
    String listText = cursor.getString(cursor
            .getColumnIndexOrThrow(DataHandler.MY_TEXT));
            TextView m_text = (TextView) view.findViewById(R.id.my_text);
    if (m_text != null) {
          m_text.setText(listText);
          long pos = cursor.getLong(cursor.getColumnIndex(DataHandler.ID)); // DataHandler.ID will point to the column _id
          if((positionHide.get(pos) != null)&&(positionHide.get(pos))) {
                        // We should hide the text view
                        m_text.setVisibility(View.GONE);
              } else {
                    // We should display the text view
                        m_text.setVisibility(View.VISIBLE);
              }
            }
}

Чтобы это работало, в вашей базе данных должен быть столбец _id INTEGER PRIMARY KEY AUTOINCREMENT (также добавленный в запрос).

...