问题
I'm trying to get the selected item within my list view to stay highlighted when I select it but for some reason it won't do that the moment the selected item is not in view. E.g. When I select Item 4, that list item does get highlighted but when I scroll through the list it doesn't stay highlighted and then other items randomly become highlighted. Even when I return to Item 4, that item is no longer highlighted. I really don't understand why this is happening. What can be done to resolve this issue? All relevant help would be appreciated.
fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragmentmain">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="false"
android:layout_centerHorizontal="true"
android:choiceMode="singleChoice"/>
</LinearLayout>
MainListAdapter.java
public class MainListAdapter extends BaseAdapter implements Filterable {
private List<Main> mData;
private List<Main> mFilteredData;
private LayoutInflater mInflater;
private ItemFilter mFilter;
public MainListAdapter (List<Main> data, Context context) {
mData = data;
mFilteredData = new ArrayList(mData);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return mFilteredData.size();
}
@Override
public Main getItem(int position) {
return mFilteredData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, parent, false);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.item);
holder.description = (TextView) convertView.findViewById(R.id.item_description);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Main main = getItem(position);
holder.title.setText(main.getContinent());
holder.description.setText(main.getDescription());
if (main.isSelected()) {
convertView.setBackgroundColor(Color.parseColor("#1C3F96"));
holder.title.setTextColor(Color.parseColor("#FFFFFF"));
holder.description.setTextColor(Color.parseColor("#FFFFFF"));
} else {
convertView.setBackgroundColor(Color.TRANSPARENT);
holder.title.setTextColor(Color.parseColor("#FFFFFF"));
holder.description.setTextColor(Color.parseColor("#B5B5B5"));
}
holder.title.setText(mFilteredData.get(position).getContinent());
holder.description.setText(mFilteredData.get(position).getDescription());
return convertView;
}
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ItemFilter();
}
return mFilter;
}
/**
* View holder
*/
static class ViewHolder {
private TextView title;
private TextView description;
}
/**
* Filter for filtering list items
*/
/**
* <p>An array filter constrains the content of the array adapter with
* a prefix. Each item that does not start with the supplied prefix
* is removed from the list.</p>
*/
private class ItemFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (TextUtils.isEmpty(constraint)) {
results.count = mData.size();
results.values = new ArrayList(mData);
} else {
//Create a new list to filter on
List<Main> resultList = new ArrayList<Main>();
for (Main str : mData) {
if (str.getContinent().toLowerCase().contains(constraint.toString().toLowerCase())) {
resultList.add(str);
}
}
results.count = resultList.size();
results.values = resultList;
}
return results;
}
/**
* Runs on ui thread
* @param constraint the constraint used for the result
* @param results the results to display
*/
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count == 0) {
mFilteredData.clear();
notifyDataSetInvalidated();
} else {
mFilteredData = (ArrayList<Main>)results.values;
notifyDataSetChanged();
}
}
}
}
Main.java (in the "data" package)
public class Main {
public Main(){}
private String continent;
private String description;
private boolean selected;
public String getContinent(){
return continent;
}
public void setContinent(String continent){
this.continent = continent;
}
public String getDescription(){
return description;
}
public void setDescription(String description){
this.description = description;
}
private int _id;
public void getID(int _id){
this._id = _id;
}
public int setID(){
return _id;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
MainActivity.java
public class MainActivity extends ActionBarActivity {
private boolean mTwoPane;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentMain newFragment = new FragmentMain();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.master_container, newFragment);
transaction.commit();
if (findViewById(R.id.detail_container) != null) {
mTwoPane = true;
}
}
@Override
protected void onNewIntent(Intent intent) {
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
//use the query to search your data somehow
}
}
}
FragmentMain.java
public class FragmentMain extends ListFragment implements SearchView.OnQueryTextListener {
private MainListAdapter mAdapter;
public FragmentMain() {
// Required empty constructor
}
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
*/
public boolean mTwoPane;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
//Tell the system to call onCreateOptionsMenu
setHasOptionsMenu(true);
initialize(view);
return view;
}
List<Main> list = new ArrayList<>();
private void initialize(View view) {
String[] items = getActivity().getResources().getStringArray(R.array.items);
String[] itemDescriptions = getActivity().getResources().getStringArray(R.array.item_descriptions);
for (int n = 0; n < items.length; n++){
Main world = new Main();
world.setID();
world.setContinent(items[n]);
world.setDescription(itemDescriptions[n]);
list.add(world);
}
mAdapter = new MainListAdapter(list, getActivity());
setListAdapter(mAdapter);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
View v = getView();
mTwoPane = getActivity().findViewById(R.id.detail_container) != null;
ListView lv = (ListView)v.findViewById(android.R.id.list);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// get the adapter, then get the name from the adapter at that position
MainListAdapter adapter = (MainListAdapter) parent.getAdapter();
Main main = adapter.getItem(position);
if (mTwoPane) {
setItemNormal();
View rowView = view;
setItemSelected(rowView);
Fragment newFragment;
switch (position) {
case 0:
newFragment = new Fragment0();
break;
case 1:
newFragment = new Fragment1();
break;
case 2:
newFragment = new Fragment2();
break;
case 3:
newFragment = new Fragment3();
break;
case 4:
newFragment = new Fragment4();
break;
case 5:
newFragment = new Fragment5();
break;
case 6:
newFragment = new Fragment6();
break;
case 7:
newFragment = new Fragment7();
break;
case 8:
newFragment = new Fragment8();
break;
case 9:
newFragment = new Fragment9();
break;
case 10:
newFragment = new Fragment10();
break;
case 11:
newFragment = new Fragment11();
break;
case 12:
newFragment = new Fragment12();
break;
case 13:
newFragment = new Fragment13();
break;
case 14:
newFragment = new Fragment14();
break;
case 15:
newFragment = new Fragment15();
break;
case 16:
newFragment = new Fragment16();
break;
case 17:
newFragment = new Fragment17();
break;
case 18:
newFragment = new Fragment18();
break;
case 19:
newFragment = new Fragment19();
break;
case 20:
newFragment = new Fragment20();
break;
default:
newFragment = new Fragment0();
}
MainActivity activity = (MainActivity) view.getContext();
FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.anim.fade_out, R.anim.fade_in);
transaction.replace(R.id.detail_container, newFragment);
transaction.commit();
} else {
Intent intent;
if (main.equals(view.getResources().getString(R.string.item0))) {
intent = new Intent(getActivity(), Activity0.class);
} else if (main.equals(view.getResources().getString(R.string.item1))) {
intent = new Intent(getActivity(), Activity1.class);
} else if (main.equals(view.getResources().getString(R.string.item2))) {
intent = new Intent(getActivity(), Activity2.class);
} else if (main.equals(view.getResources().getString(R.string.item3))) {
intent = new Intent(getActivity(), Activity3.class);
} else if (main.equals(view.getResources().getString(R.string.item4))) {
intent = new Intent(getActivity(), Activity4.class);
} else if (main.equals(view.getResources().getString(R.string.item5))) {
intent = new Intent(getActivity(), Activity5.class);
} else if (main.equals(view.getResources().getString(R.string.item6))) {
intent = new Intent(getActivity(), Activity6.class);
} else if (main.equals(view.getResources().getString(R.string.item7))) {
intent = new Intent(getActivity(), Activity7.class);
} else if (main.equals(view.getResources().getString(R.string.item8))) {
intent = new Intent(getActivity(), Activity8.class);
} else if (main.equals(view.getResources().getString(R.string.item9))) {
intent = new Intent(getActivity(), Activity9.class);
} else if (main.equals(view.getResources().getString(R.string.item10))) {
intent = new Intent(getActivity(), Activity10.class);
} else if (main.equals(view.getResources().getString(R.string.item11))) {
intent = new Intent(getActivity(), Activity11.class);
} else if (main.equals(view.getResources().getString(R.string.item12))) {
intent = new Intent(getActivity(), Activity12.class);
} else if (main.equals(view.getResources().getString(R.string.item13))) {
intent = new Intent(getActivity(), Activity13.class);
} else if (main.equals(view.getResources().getString(R.string.item14))) {
intent = new Intent(getActivity(), Activity14.class);
} else if (main.equals(view.getResources().getString(R.string.item15))) {
intent = new Intent(getActivity(), Activity15.class);
} else if (main.equals(view.getResources().getString(R.string.item16))) {
intent = new Intent(getActivity(), Activity16.class);
} else if (main.equals(view.getResources().getString(R.string.item17))) {
intent = new Intent(getActivity(), Activity17.class);
} else if (main.equals(view.getResources().getString(R.string.item18))) {
intent = new Intent(getActivity(), Activity18.class);
} else if (main.equals(view.getResources().getString(R.string.item19))) {
intent = new Intent(getActivity(), Activity19.class);
} else if (main.equals(view.getResources().getString(R.string.item20))) {
intent = new Intent(getActivity(), Activity20.class);
} else {
intent = new Intent(getActivity(), Activity0.class);
}
startActivity(intent);
}
}
public void setItemSelected(View view) {
View rowView = view;
view.setBackgroundColor(Color.parseColor("#1C3F96"));
TextView tv0 = (TextView) rowView.findViewById(R.id.item);
tv0.setTextColor(Color.parseColor("#FFFFFF"));
TextView tv1 = (TextView) rowView.findViewById(R.id.item_description);
tv1.setTextColor(Color.parseColor("#FFFFFF"));
}
public void setItemNormal() {
for (int i = 0; i < getListView().getChildCount(); i++) {
View v = getListView().getChildAt(i);
v.setBackgroundColor(Color.TRANSPARENT);
TextView tv0 = ((TextView) v.findViewById(R.id.item));
tv0.setTextColor(Color.WHITE);
TextView tv1 = ((TextView) v.findViewById(R.id.item_description));
tv1.setTextColor(Color.parseColor("#B5B5B5"));
}
}
});
super.onActivityCreated(savedInstanceState);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem searchViewMenuItem = menu.findItem(R.id.action_search);
SearchView mSearchView = (SearchView) MenuItemCompat.getActionView(searchViewMenuItem);
int searchImgId0 = android.support.v7.appcompat.R.id.search_button;
ImageView v0 = (ImageView) mSearchView.findViewById(searchImgId0);
v0.setImageResource(R.drawable.ic_action_search_light);
int searchImgId1 = android.support.v7.appcompat.R.id.search_close_btn;
ImageView v1 = (ImageView) mSearchView.findViewById(searchImgId1);
v1.setImageResource(R.drawable.ic_action_content_clear_light);
super.onPrepareOptionsMenu(menu);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Set up search view
inflater.inflate(R.menu.menu_main, menu);
MenuItem item = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setIconifiedByDefault(true);
searchView.clearAnimation();
searchView.setOnQueryTextListener(this);
}
@Override
public boolean onQueryTextSubmit(String newText) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
mAdapter.getFilter().filter(newText);
return false;
}
}
list_item.xml
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:baselineAligned="false"
android:paddingStart="12dp"
android:paddingEnd="12dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="@+id/item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:textColor="?android:attr/textColorPrimary" />
<TextView android:id="@+id/item_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/item"
android:layout_alignStart="@id/item"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary" />
</RelativeLayout>
Updated screenshot 31/07/2015
回答1:
Android ListView reuses its views while you scroll it. You need to store information about a selected item in an item object and check if it is selected inside getView.
Call setItemSelected if it is selected and setItemNormal otherwise. This way you will update the selected state of each item while you scrolling the list.
EDIT
@Override
public Main getItem(int position) {
return mFilteredData.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, parent, false);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.item);
holder.description = (TextView) convertView.findViewById(R.id.item_description);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Main main = getItem(position);
holder.title.setText(main.getContinent());
holder.description.setText(main.getDescription());
if (main.isSelected()) {
convertView.setBackgroundColor(Color.parseColor("#1C3F96"));
holder.title.setTextColor(Color.parseColor("#FFFFFF"));
holder.description.setTextColor(Color.parseColor("#FFFFFF"));
} else {
convertView.setBackgroundColor(Color.TRANSPARENT);
holder.title.setTextColor(Color.parseColor("#FFFFFF"));
holder.description.setTextColor(Color.parseColor("#B5B5B5"));
}
return convertView;
}
Inside your onItemClick:
...
switch (position) {
case 0:
newFragment = new Fragment0();
break;
case 1:
newFragment = new Fragment1();
break;
// etc..
default:
newFragment = new Fragment0();
}
来源:https://stackoverflow.com/questions/31442067/list-item-wont-stay-selected-despite-setting-necessary-properties