I try to remove a specific item from a listView but it's always remove the last item.
I create a custom adapter to my listview.
I try to search for a solution and i found some posts about this problem but I still didn't success to solve the problem
custom adapter below:
public class ListViewAdapter extends BaseAdapter{
public ArrayList<HashMap<String, String>> list;
public static final String WORD_COLUMN="First";
public static final String TRAN_COLUMN="Second";
Activity activity;
TextView txtFirst;
TextView txtSecond;
public ListViewAdapter(Activity activity,ArrayList<HashMap<String, String>> list){
super();
this.activity=activity;
this.list=list;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=activity.getLayoutInflater();
if(convertView == null){
convertView=inflater.inflate(R.layout.column_row, null);
txtFirst=(TextView) convertView.findViewById(R.id.wordColumn);
txtSecond=(TextView) convertView.findViewById(R.id.tranColumn);
}
HashMap<String, String> map=list.get(position);
txtFirst.setText(map.get(WORD_COLUMN));
txtSecond.setText(map.get(TRAN_COLUMN));
return convertView;
}
}
activity code below:
public class MainActivity extends AppCompatActivity{
private ListView lv;
private ArrayList<HashMap<String, String>> hashList;
private ListViewAdapter adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView)findViewById(R.id.gvWords);
hashList = new ArrayList<HashMap<String, String>>();
adapter=new ListViewAdapter(this, hashList);
lv.setAdapter(adapter);
onClickButtons();
}
public void onClickButtons()
{
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
hashList.remove(i);
adapter.notifyDataSetChanged();
}
});
}
Thank's :)
You can try to access and remove clicked object via getItemAtPosition(position) and then remove it from ArrayList via .remove(Object o)
Your listener will therefore look like this:
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
hashList.remove(lv.getItemAtPosition(i));
adapter.notifyDataSetChanged();
}
});
This approach is mentioned in official doc: https://developer.android.com/reference/android/widget/AdapterView.OnItemClickListener.html
Implementers can call getItemAtPosition(position) if they need to access the data associated with the selected item.
after refreshing it's remove the right item
You've cached the two TextViews, which aren't updated as part of notifying the adapter.
Alter the convertView check and remove those fields, then lookup how to implement the ViewHolder pattern (or use a RecyclerView)
I found this problem,
and removed the if(convertView == null){ It's working,
Please let us know for this reason.
Related
I have three fragments switched using a ViewPager and the third one contains a ListView.
My problem is that the ListView is not populated on the first time that I switch to that fragment. I have to switch back to the first then back to the third again and only will the ListView be populated. What seems to be the problem here?
How does ViewPager works anyways?
Here is my TabAdapter
public class TabAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
TabAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
}
Here is ListAdapter for the listView
public class ListAdapter extends BaseAdapter {
private ArrayList data = new ArrayList();
public ListAdapter(LinkedHashMap<String, ArrayList<String>> lhm) {
try {
data.addAll(lhm.entrySet());
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public int getCount() {
return data.size();
}
#Override
public LinkedHashMap.Entry<String, ArrayList<String>> getItem(int position) {
return (LinkedHashMap.Entry) data.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#NonNull
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
final LinkedHashMap.Entry<String, ArrayList<String>> item = getItem(position);
final ArrayList quotesList = item.getValue();
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.archive_list, parent, false);
}
TableRow tableRow = convertView.findViewById(R.id.container);
TextView title = convertView.findViewById(R.id.title);
ImageView copy = convertView.findViewById(R.id.copy);
copy.setVisibility(View.INVISIBLE);
title.setText(item.getKey() + " Quotes");
tableRow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getContext(), ViewActivity.class);
intent.putExtra("title", item.getKey());
intent.putStringArrayListExtra("quotes", quotesList);
if (interstitialAd.isLoaded()) {
interstitialAd.show();
startActivity(intent);
} else {
startActivity(intent);
}
}
});
return convertView;
}
}
Update
The problem seems to be from the Linkedhashmap. I tried manually putting values into the Hashmap and it worked. The problem now is my current code. I populate my hashmap by retrieving data from firebase and that seems to be the problem? Pershaps it isn't populated as quickly?
private void initArchives() {
DatabaseReference dBase = FirebaseDatabase.getInstance().getReference().child("archive");
dBase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot snapshot : dataSnapshot.getChildren()) {
DataPojo dp = snapshot.getValue(DataPojo.class);
hm.put(dp.getName(), dp.getMessages());
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_archive, container, false);
listView = view.findViewById(R.id.listView);
searchView = view.findViewById(R.id.searchView);
initArchives();
listAdapter = new ListAdapter(hm);
listView.setAdapter(listAdapter);
listView.invalidateViews();
loadAds();
return view;
}
First of all FragmentStatePagerAdapter is really a pain in the ass. But we have to work with that. I suggest you to Ctrl + click on FragmentStatePagerAdapter and read source code.
Another thing is adding fragments to your ArrayList with addFragment() method might not be the best idea since FragmentStatePagerAdapter is saving the states of the fragments and loads them from its own FragmentManager.
So the fragment you added might not be the fragment you are getting.
A possible solution to that would be using tags.
There are some must read articles about the topic here here and here.
And oh one other thing. ViewPager creates three fragments at a time when using FragmentStatePagerAdapter. First it creates fragment to display and next the fragment on the right and last the fragment on the left. Since you have three fragments, the last (3rd) fragment is not created right away (There is no fragment on the left of the first fragment). Maybe you are loading some data that takes time to download on the third fragment? And next time you display the 3rd fragment it loads from the saved state of FragmentStatePagerAdapter. These are just some possibilities to think about. Not necessarily is the right solution. Good luck.
public class SingleListAdapter extends BaseAdapter {
public Context ctx;
LayoutInflater lInflater;
List<String> data;
public SingleListAdapter(Context context, List<String> data) {
ctx = context;
this.data = data;
lInflater = (LayoutInflater) ctx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.single_choice_items, parent, false);
}
((TextView) view.findViewById(R.id.singleitemId)).setText(data.get(position));
return view;
}
}
This is my adapter class :
String[] data = {"10-11 Am", "11-12Am", "12-2Pm", "2-4PM", "4-6Pm"};
List<String> list = new ArrayList<String>();
for (int i = 0; i < data.length; i++) {
list.add(data[i]);
}
SingleListAdapter adapter = new SingleListAdapter(this, list);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
valueoflist= data[i];
}
});
this is my lsitview itemclick function i have textview and checkbox in listview adapter i am printing value in a textview and i am able to get data of Particular item on listview item click i want when i click on item list then that particular check box should enable please suggest me how we can do this like and i want single choice checked item click please help me suggest me how we can do this .
In onItemClick method you can call your checkBox object and you can work with it.
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
valueoflist= data[i];
CheckBox chk = (CheckBox)view.findViewById(R.id.your_check_box_id);
chk.setChecked(true);
}
});
I hope it will help you
Try this:
listview.setOnItemClickListener(new OnMyItemClickListener());
and declare:
private class OnMyItemClickListener implements
ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
valueoflist= data[i];
CheckBox chk = (CheckBox)view.findViewById(R.id.your_check_box_id);
chk.setChecked(true);
}
}
But.. a question.. can you show the listview initialize?
i got this problem yesterday:
Here I have a list returned by server, and there is a Hashmap list(List) and a Hashmap inside the list.And I got two situations, one is when the hashmap list is null, I add a new item into it,and then call notifyDataSetChanged() doesn't work, and the other situation is when i changed the value in hashmap, and notifyDataSetChanged(), it doesn't refresh either.And I'm sure the data has been changed successfully.
it shows in A activity and changed data in B activity.
A activity:
protected List<CommentEntity> mDataList;
protected ListView mListView;
protected BaseListAdapter mAdapter;
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
int position = data.getIntExtra("position", -1);
if (position > -1) {
CommentEntity entity = (CommentEntity) data.getSerializableExtra(AppVars.Keys.EXTRA_ENTITY);
mDataList.set(position, entity); // I want this list update
mAdapter.notifyDataSetChanged();
} else {
// error
}
}
public class BaseListAdapter extends BaseAdapter {
#Override
public int getCount() {
return mDataList == null ? 0 : mDataList.size();
}
#Override
public Object getItem(int position) {
return mDataList == null ? null : mDataList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// actually this adapter is written in MyBaseFragment, and the child
// Fragment will override setupItemView() method.it's working fine
return setupItemView(position, convertView, parent);
}
}
B activity:
private CommentEntity mCommentEntity;
// the list below is inside CommentEntity, QuoteEntity is extends HashMap<>.
private List<QuoteEntity> mQuoteList;
private QuoteAdapter mAdapter;
public void update(QuoteEntity newQuote) {
mQuoteList.add(newQuote);
mCommentEntity.setReplyRows(mQuoteList);
mAdapter.notifyDataSetChanged();// This adapter is just working fine.
setResult(-1, getIntent().putExtra(AppVars.Keys.EXTRA_ENTITY, mCommentEntity));
}
Try resetting listview instead of using notifyDataSetChanged();
ListView lv = (ListView)FindViewById(R.id.lv);
BaseListAdapter aa = new BaseListAdapter(//constructor's parameters);
lv.setAdapter(aa);
I have a dynamic array of drawables and want to display them in a scrollable list. The thing I am having the most trouble with is the array adapter. I don't get any compile time errors with this code, but the runtime error I get is -
Process: com.example.michael.myandroidappactivity, PID: 12297
java.lang.IllegalStateException: ArrayAdapter requires the resource ID to be a TextView
I don't want to use a textview though! Here's the main code-
public class cards extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_old_cards);
ListView list = (ListView)findViewById(R.id.showCardList);
cardPile tmp = cardPile.getInstance();
ArrayList<Integer> discardPile = tmp.getDiscardPile();
ArrayAdapter<Integer> imgAdapt = new ArrayAdapter<Integer>(this,R.layout.listview_layout,discardPile);
list.setAdapter(imgAdapt);
}
}
You have to create a new class that extends the BaseAdapter interface and modify the getView method to return the view you want to show in your ListView. For example:
public class ImageAdapter extends BaseAdapter
{
private Context context;
private ArrayList<Integer> imagesIds;
public ImageAdapter(Context _context, ArrayList<Integer> _imageIds)
{
context = _context;
imageIds = _imageIds;
}
#Override
public int getCount()
{
return imgIds.size();
}
#Override
public Object getItem(int position)
{
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ImageView view;
if( convertView != null ) // recycle call
{
view = (ImageView) convertView;
}
else
{
view = new ImageView(context);
image.setBackgroundResource(imageIds.get(position));
}
return view;
}
}
Then modify your listView adapter as:
list.setAdapter( new ImageAdapter( this, discardPile) );
I am struggling with trying to implement an OnLongClick feature - I can't understand where to add a listener and to define the resulting method.
The implementation i have used uses an adapter - and does not have an onClickListener, but works jsut fine. can anyone suggest where/how to implement OnLongClick listener
I don't need every item in the list to perform different actions - just for anywere on the screen to pick up the long press
public class CombChange extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ListEdit(this, symbols));
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
String selectedValue = (String) getListAdapter().getItem(position);
if (lastPressed.equals(selectedValue) ){
count++;}
}
public class ListEdit extends ArrayAdapter<String> {
private final Context context;
private final String[] values;
public ListEdit(Context context, String[] values) {
super(context, R.layout.activity_comb_change, values);
this.context = context;
this.values = values;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.activity_comb_change, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.label);
ImageView imageView = (ImageView) rowView.findViewById(R.id.logo);
textView.setText(values[position]);
// Change icon based on name
String s = values[position];
if (s.equals("a")) {
imageView.setImageResource(R.drawable.a);
return rowView;
}
}
Try this:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
v.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
String selectedValue = (String) getListAdapter().getItem(position);
if (lastPressed.equals(selectedValue) ){
count++;}
return false;
}
});
}
It is unfortunate that a ListActivity does not have a protected onListItemLongClick() method similar to the onListItemClick() function.
Instead, you can add setOnLongClickListener() to the top-level layout item (or any View) in your adapter's getView() function.
Example:
myView.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
// Do something here.
return true;
}
});
Warning, the OnLongClickListener you put onto your list item may hide exposure to the onListItemClick() function you already have working for the list. If this is the case, you will also have to add setOnClickListener() to getView() and use it instead.
in your getView you can say
rowview.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View arg0) {
//Do your stuff here
return false;
}
});