Поиск правильного дочернего представления ListView при нажатии кнопки внутри него

#android #listview #onclicklistener #baseadapter

#Android #listview #onclicklistener #baseadapter

Вопрос:

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

У меня есть a ListView , в каждой строке у меня есть кнопка и a TextView , мой эксперимент будет заключаться в том, чтобы щелкнуть a Button и окрасить строку в зеленый цвет, вот код:

Редактировать:

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

     package com.ziv.test;

import java.util.ArrayList;

import com.ziv.test.Fr.mAdapter.ViewHolder;

import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

public class Fr extends Fragment {

    ArrayList<String> list;
    private ListView lv;

    public Fr() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_main, container, false);
        list = new ArrayList<String>();

        for (int i = 0; i < 50; i  ) {
            list.add("item number "   i);
        }

        lv = (ListView) view.findViewById(R.id.listView1);

            mAdapter adapter = new mAdapter(list, lv);
            lv.setAdapter(a

dapter);

        return view;
    }

    public class mAdapter extends BaseAdapter {
    ArrayList<String> list;
    private LayoutInflater inflater;
    private ListView lv;

    // boolean[] for button state:
    private Boolean[] clickedButtonPositions;

    public mAdapter(ArrayList<String> list, ListView lv) {

        this.list = list;
        this.lv = lv;
        inflater = (LayoutInflater) getActivity().getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
         this.clickedButtonPositions = new Boolean[list.size()];
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // here you write everything is related to views...
        // do not forget to reuse...

        ViewHolder vh;
        if (convertView == null) {

            vh = new ViewHolder();
            convertView = inflater.inflate(R.layout.list_cell, null);

            vh.text = (TextView) convertView.findViewById(R.id.list_test);
            vh.btn = (Button) convertView.findViewById(R.id.list_button);

            convertView.setTag(vh);

        } else {


            vh = (ViewHolder) convertView.getTag();

        }
        vh.text.setText(list.get(position));

        vh.btn.setTag(R.id.list_button, position);

        vh.btn.setOnClickListener(OnClickButton);



        return convertView;

    }

    public class ViewHolder {
        TextView text;
        Button btn;

    }



    private View.OnClickListener OnClickButton = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // v will always be the view that received the click event, no
            // need to check.
            int pos = (int) v.getTag(R.id.list_button);
            LinearLayout view = (LinearLayout) lv.getChildAt(pos);

            // Switching the 'clicked' value for this button - If you want
            // the button to "turn off" the view
            clickedButtonPositions[pos] = !clickedButtonPositions[pos];
            // If you don't want the button to "turn off" the view use this
            // line instead:
            // clickedButtonPositions[pos] = true;

            // save button state in a local variable, optional
            boolean clicked = clickedButtonPositions[pos];

            // If you want a "turn off" behavior use this line with the '?:'
            // operator
            view.setBackgroundColor(clicked ? Color.GREEN : Color.LTGRAY);
            // If you don't want a "turn off" behavior this will do:

        }
    };
}
 

}

введите описание изображения здесь

Однако, к моему большому разочарованию, строка, которую я нажимаю, была не единственной, окрашенной в зеленый цвет, ее переработанная строка также была окрашена, та, которая была сразу за пределами экрана. как я могу изолировать нужную строку в событии щелчка?

Комментарии:

1. что-то не так с моим вопросом? почему downvote?

Ответ №1:

Я столкнулся с аналогичной проблемой в своем проекте и расширял базовый адаптер, как и вы. Мое решение было действительно простым. Это выглядит так:

 if(buttonClick)//any boolean variable indicating clicked
{
view.setBackgroundColor(Color.GREEN);
}else{
view.setBackgroundColor(Color.WHITE);
}
 

Комментарии:

1. вы меняете фон на зеленый, а задний на белый?, эксперимент маломасштабный, но в конечном итоге я захочу внести большие изменения в представление, а не просто изменить цвет фона

2. Так получилось, что когда я изменил цвет фона одного элемента, другой в какой-то другой позиции также изменился. Чтобы избежать этого, я сбрасываю цвет фона по умолчанию внутри getView. Я могу опубликовать java-файл, который я использовал для его преодоления, но я сомневаюсь, что это будет плодотворно. код, который я упомянул, является базовой концепцией моего решения

Ответ №2:

Вы должны добавить логический массив для всех ваших ListView элементов.

В onClick() , установите значение true / false только для правильной позиции. Затем вызовите notifyDatasetChanged() свой адаптер.

В getView() , установите цвет в зависимости от вашего логического массива.

Комментарии:

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

2. Извините, но это не эксперимент. Удачи в поиске сложного решения этой простой проблемы ;-).

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