#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. почему сарказем? я пытаюсь выяснить, есть ли правильный способ справиться с этой ситуацией, поскольку моя точная проблема с моим точным кодом не поможет другим людям, которые сталкиваются с этой проблемой.