How to pass Hashmap data to BaseAdapter in Android - android

I am currently implementing Sectioned Listview Adapter PinnedSectioned Listview
Currently i have changed the implementation to base adapter but I am facing some problem in passing the values to the base adapter
How can I pass Hashmap value to the adapter.
Example-
HashMap<Integer, ArrayList<Test>> example = new HashMap<Integer, ArrayList<Test>>();
Base Adapter implementation
static class MyPinnedSectionListAdapter extends BaseAdapter implements PinnedSectionListView.PinnedSectionListAdapter{
private ArrayList mList;
private Context mContext;
private LayoutInflater mInflater;
ArrayList<Item> value;
public static final int FIRST = 0;
public static final int SECOND = 1;
int size=0;
private String[] mKeys;
private Map<String, ArrayList<Item>> mData = new HashMap<String, ArrayList<Item>>();
public MyPinnedSectionListAdapter(Context context, Map<String, ArrayList<Item>> map){
mList=new ArrayList();
mData=map;
mKeys = mData.keySet().toArray(new String[mData.size()]);
for (Map.Entry<String, ArrayList<Item>> entry : map.entrySet()) {
value= entry.getValue();
size+=value.size();
System.out.println();
}
System.out.println("size" + size);
mList.addAll(map.entrySet());
this.mContext = context;
this.mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public boolean isItemViewTypePinned(int viewType) {
if(viewType == SECOND){
return true;
}else{
return false;
}
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Object getItem(int position) {
return mData.get(mKeys[position]);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
if(viewType == FIRST){
convertView = mInflater.inflate(R.layout.item,parent,false);
String key = mKeys[position];
String Value = getItem(position).toString();
((TextView)convertView.findViewById(R.id.textView1)).setText(Value);
}
if(viewType == SECOND){
String key = mKeys[position];
String Value = getItem(position).toString();
convertView = mInflater.inflate(R.layout.section,parent,false);
((TextView)convertView.findViewById(R.id.textView1)).setText(Value);
}
return convertView;
}
#Override
public int getItemViewType(int position) {
#SuppressWarnings("unchecked")
ArrayList<Item> item = (ArrayList<Item>) getItem(position);
if (item.get(position).type == 0){
return FIRST;
}else{
return SECOND;
}
}
#Override
public int getViewTypeCount() {
return 2;
}
}
POJO:
static class Item {
public static final int ITEM = 0;
public static final int SECTION = 1;
public final int type;
public final String text;
public int sectionPosition;
public int listPosition;
public Item(int type, String text) {
this.type = type;
this.text = text;
}
#Override public String toString() {
return text;
}
}
CODE:
HashMap> example = new HashMap>();
ArrayList<Item> test1 = new ArrayList<Item>();
test1.add( new Item(Item.SECTION, "Section1"));
test1.add( new Item(Item.ITEM, "Section2"));
test1.add( new Item(Item.ITEM, "Section3"));
ArrayList<Item> test2 = new ArrayList<Item>();
test2.add( new Item(Item.SECTION, "Section4"));
test2.add( new Item(Item.ITEM, "Section5"));
test2.add( new Item(Item.ITEM, "Section6"));
example.put("1", test1);
example.put("2", test2);
setListAdapter(new MyPinnedSectionListAdapter(this,example));
I am getting ouput like :
[Section1 , [Section 2], [Section3]
[Section 4],[Section 5],[Section 6]

Why are you not making constructor for your MyPinnedSectionListAdapter with HashMap<K,V> argument. and pass your HashMap<Integer, ArrayList<Test>> example to it,
Something like,
public MyPinnedSectionListAdapter(Context context, HashMap<Integer, ArrayList<Test>> hashMap){...}
Edit:
As per #av_lee 's comment.
You can use Guava's Multimap class
with properties like,
A key is contained in the multimap if and only if it maps to at least
one value. Any operation that causes a key to have zero associated
values has the effect of removing that key from the multimap.
The total entry count is available as size().

Related

How to get listview items both visible and invisible child values

This loop return only visible position values.However I need the values of child items that are invisible.
for (int i = 0; i < material_issue_list.getCount(); i++) {
View layout = materialIssueAdapter.getViewByPositio(i, material_issue_list);
LinearLayout listItem = (LinearLayout) materialIssueAdapter.getViewByPositio(i, material_issue_list);
String batchSTR = ((AutoCompleteTextView) listItem.findViewById(R.id.batch_AutoComplete)).getText().toString();
String qtySTR = ((EditText) listItem.findViewById(R.id.issue_qty_ETD)).getText().toString();}
My full adapter class,Some one help me suggest to get the correct output.My problem I'm getting null values from the views that are invisible.
Only the visible values are being updated to arraylist.
Thanks in advance.
public class IssueMaterialAdapter extends BaseAdapter {
private Activity activity;
public static ArrayList Dummylist;
private static LayoutInflater inflater = null;
public Resources res;
public static ArrayList<BatchNav> batchNavs_Arr;
static ArrayList<String> batch_Arr;
public static ArrayList<String> batch_data;
public static ArrayList<String> issue_qty;
LinkedHashSet<String> hashSet;
public static ArrayList<BatchModel> batchModels = new ArrayList<BatchModel>();
public static HashMap<ViewHolder, String> batch_map;
public static HashMap<ViewHolder, String> qty_map;
HashMap<String, String> mValues = new HashMap<String, String>();
ArrayList<SaveDataModel> saveDataModels;
public IssueMaterialAdapter(Activity a, ArrayList dummy) {
activity = a;
Dummylist = dummy;
loadBatch();
this.batch_map = new HashMap<>();
inflater = (LayoutInflater) activity.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
if (Dummylist.size() <= 0)
return 1;
return Dummylist.size();
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View vi = convertView;
final ViewHolder holder;
if (convertView == null) {
vi = inflater.inflate(R.layout.material_issue_details_list, null);
holder = new ViewHolder();
holder.batch = (AutoCompleteTextView) vi.findViewById(R.id.batch_AutoComplete);
holder.issue = (EditText) vi.findViewById(R.id.issue_qty_ET);
holder.material_descrption = (TextView) vi.findViewById(R.id.material_desc);
holder.unit_issue = (EditText) vi.findViewById(R.id.unit_issue_ET);
holder.matnr = (TextView) vi.findViewById(R.id.matnr);
holder.prdgrp = (TextView) vi.findViewById(R.id.prod_grp);
vi.setTag(holder);
batch_map.put(holder, "");
FilterWithSpaceAdapter<String> farmer_co_no_adapter = new FilterWithSpaceAdapter<String>(activity,
R.layout.custom_items, batch_Arr);
holder.batch.setAdapter(farmer_co_no_adapter);
holder.batch.setThreshold(1);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
if (Dummylist.size() == AgriDistributionActivity.get_materials.size()) {
holder.material_descrption.setText(AgriDistributionActivity.get_materials.get(position));
holder.matnr.setText(AgriDistributionActivity.get_matnr.get(position));
holder.prdgrp.setText(AgriDistributionActivity.selected_prdgrp.get(position));
}
try {
if (saveDataArr.size() > 0) {
holder.batch.setText(saveDataArr.get(position).getBatch());
holder.issue.setText(saveDataArr.get(position).getQty());
holder.unit_issue.setText(saveDataArr.get(position).getQty_uom());
}
} catch (Exception e) {
}
return vi;
}
public static class ViewHolder {
public EditText issue, unit_issue;
public AutoCompleteTextView batch;
public TextView material_descrption, matnr,prdgrp;
}
private void loadBatch() {
batch_Arr = new ArrayList<String>();
batchNavs_Arr = new ArrayList<BatchNav>();
hashSet = new LinkedHashSet<>();
BatchNavEntityCollection batchNavEntityCollection = BatchNavEntityCollection.getInstance();
batchNavs_Arr = batchNavEntityCollection.getBatchOutVal();
for (int i = 0; i < batchNavs_Arr.size(); i++) {
String batch = batchNavs_Arr.get(i).getCharg();
batch_Arr.add(batch);
hashSet.addAll(batch_Arr);
batch_Arr.clear();
batch_Arr.addAll(hashSet);
}
}
public View getViewByPositio(int position, ListView listView) {
final int firstListItemPosition = listView.getFirstVisiblePosition();
final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;
if (position < firstListItemPosition || position > lastListItemPosition) {
return listView.getAdapter().getView(position, null, listView);
} else {
final int childIndex = position - firstListItemPosition;
return listView.getChildAt(childIndex);
}
}
}
You have saveDataArr list which holds all your data.
You can add a getter if you want to do it from an activity , add something like this to your adapter :
private SaveDataModelsendLog(int position) {
return saveDataArr(position);
}
That should do the trick , having said all that you should also look at the difference between static and non-static variables ,
it seems like you have to many of them ,
Enjoy.

I meet a something wrong about IndexOutOfBoundsException

I have a Json data like ,I want to show the information in my listView so I parse them into a ArrayList<String> and then add to the adapter.
{
"areas": [
{
"fieldTag": "1",
"areaId": 2,
"areaName": "No.1",
"devices": [
{
"cameraName": "A",
"busyFields": "null",
"freeFields": "No.1,NO,2",
},{
"cameraName": "B"
"busyFields": "null",
"freeFields": "No.3,No.4",
}
]
}
],
"error": 0,
"message": "ok"
}
and I use Gson to parse it and I make the data to a list for show them in the Adapter,my code is :
if (mDeviceInfo.getError() == 0) {
for (int i = 0; i<mDeviceInfo.getAreas().size();i++){
adapter.addSectionHeaderItem(mDeviceInfo.getAreas().get(i).getAreaName());
for (int k = 0; k<mDeviceInfo.getAreas().get(i).getDevices().size();k++){
adapter.addItem(mDeviceInfo.getAreas().get(i).getDevices().get(k).getCameraName());
mPositionList.add(mDeviceInfo.getAreas().get(i).getDevices().get(k).getPosition());
mFreeFieldsList.add(mDeviceInfo.getAreas().get(i).getDevices().get(k).getFreeFields());
mBusyFieldsList.add(mDeviceInfo.getAreas().get(i).getDevices().get(k).getBusyFields());
}
}
adapter.addMessage(mPosition,mFreeFields,mBusyFields);
}else {
Toast.makeText(this,"get info failed",Toast.LENGTH_SHORT).show();
}
and that is my code as the Adapter:
public class CameraListAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private ArrayList<String> mData = new ArrayList<String>();
private ArrayList<String> mPosition = new ArrayList<>();
private ArrayList<String> mFreeFields = new ArrayList<>();
private ArrayList<String> mBusyFields = new ArrayList<>();
private TreeSet<Integer> sectionHeader = new TreeSet<Integer>();
private LayoutInflater mInflater;
public CameraListAdapter(Context context) {
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSectionHeaderItem(final String item) {
mData.add(item);
sectionHeader.add(mData.size() - 1);
notifyDataSetChanged();
}
public void addMessage(ArrayList<String> position,ArrayList<String> freeFields,ArrayList<String> busyFields){
mPosition = position;
mFreeFields = freeFields;
mBusyFields = busyFields;
}
#Override
public int getItemViewType(int position) {
return sectionHeader.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public boolean isEnabled(int position) {
return getItemViewType(position) != TYPE_SEPARATOR;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
int rowType = getItemViewType(position);
if (convertView == null) {
viewHolder = new ViewHolder();
switch (rowType) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.cameradetail, null);
viewHolder.mCameraName = (TextView) convertView.findViewById(R.id.cameraName);
Log.d("CameraListAdapter","position "+position);
viewHolder.mCameraName.setText(mData.get(position));
viewHolder.position = (TextView) convertView.findViewById(R.id.cameraposition);
viewHolder.position.setText(mPosition.get(position));
viewHolder.busyFields = (TextView) convertView.findViewById(R.id.busyfields);
viewHolder.busyFields.setText(mBusyFields.get(position));
viewHolder.freeFields = (TextView) convertView.findViewById(R.id.freefields);
viewHolder.freeFields.setText(mFreeFields.get(position));
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.cameratag, null);
viewHolder.mTag = (TextView) convertView.findViewById(R.id.areaName);
viewHolder.mTag.setText(mData.get(position));
break;
}
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
return convertView;
}
public static class ViewHolder {
public TextView mTag;
public TextView mCameraName;
public TextView position;
public TextView busyFields;
public TextView freeFields;
}
}
But it always show me that
java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at .CameraListAdapter.getView(CameraListAdapter.java:106)
It upset me for 2 days so are there anyone to help me ?Thank you so much
In an Adapter, the size of the data is determined by getCount, which you defined like so.
#Override
public int getCount() {
return mData.size();
}
This means that the range of positions in getView is 0 to the value returned by getCount.
But, you seem to have 4 lists of various sizes, or at least not the same size as mData
private ArrayList<String> mData = new ArrayList<String>();
private ArrayList<String> mPosition = new ArrayList<>();
private ArrayList<String> mFreeFields = new ArrayList<>();
private ArrayList<String> mBusyFields = new ArrayList<>();
I'm not sure which one is causing the problem, but, for example, this will throw an exception if mPosition doesn't hold the same amount of data as mData
viewHolder.position.setText(mPosition.get(position));
I would recommend you not have 4 separate String Arraylists since that data seems to pertain to a single Object, which if you want a proper custom Adapter, you give it a list of your Object type (parsed from Gson, for example) instead of individual pieces of an Object
When you use
#Override
public int getCount() {
return mData.size();
}
you basically tell the adapter to call the getView() method for every item in you mData list. The position argument in your getView() method corresponds to the entry in your mData list. You then use that same position argument to get data out of three other lists that are probably of different size than the mData list so one of the get(position) calls on one of the other lists will throw the exception you are seeing. This can be easily debugged if you use the debugger in Android Studio on line 106 in your adapter.

Android Custom ListView onClickListener returns null

Something very strange is happening with my custom ListView. After the list is loaded if I click on the ListItems very fast it crashes but if I give it a second then everything works fine.
My list contains section headings (see screenshot) which changes the position of the UI list from the Model List. So when I populate the ListView I do the mapping in the listAdapter class and I believe this is causing the code the crash. I click on the view before the mapping is complete and I get a "Value" of null for the given key.
public class ListAdapter extends BaseAdapter implements SectionIndexer {
private Context mContext;
private static final String TAG = "ListAdapter";
private LayoutInflater mInflater;
private ArrayList mData = new ArrayList();
// MapIndex to map the scroll alphabet to section
private HashMap<String, Integer> mapIndex;
// To return the right index otherwise the click will return wrong objects becasue the count the section headers
private ConcurrentHashMap<Integer, Integer> viewPositions;
// contains all the sections alphabets
private String[] sections;
/** Int code to represent regular list items **/
public static final int TYPE_ITEM = 0;
/** Int val to represent header list item **/
private static final int TYPE_SEPARATOR = 1;
/** There are two different items **/
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private static TextView name;
private static TextView industry;
private static UserModel user;
private ImageView logo;
private static int mCount = 0;
public ListAdapter(Context context, ArrayList<UserModel> users) {
Collections.sort(users, UserModel.Comparators.NAME);
viewPositions = new ConcurrentHashMap<Integer, Integer>();
mContext = context;
mInflater = ((Activity)mContext).getLayoutInflater();
mapIndex = new LinkedHashMap<String, Integer>();
for (int i = 0; i < users.size(); i++){
String ch = users.get(i).getFirstName().substring(0,1);
ch.toUpperCase();
/** If HashMap doesn't have the Alphabet put the new one **/
if (!mapIndex.containsKey(ch)){
mapIndex.put(ch, i);
addSeparatorItem(ch);
mCount ++;
}
addItem(users.get(i));
viewPositions.put(mCount,i);
mCount ++;
}
Set<String> sectionLetters = mapIndex.keySet();
sections = new String[sectionLetters.size()];
sectionLetters.toArray(sections);
}
public int getRealPosition(int key){
Log.d(TAG, "getRealPosition: Key = " + key + "Value = " + viewPositions.get(key));
return viewPositions.get(key);
}
public void addItem(final UserModel item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
if (mData.get(position) instanceof UserModel){
return TYPE_ITEM;
}
return TYPE_SEPARATOR;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Object getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int type = getItemViewType(position);
switch (type) {
case TYPE_ITEM:
user = ((UserModel)mData.get(position));
convertView = mInflater.inflate(R.layout.fragment_contact_list, null);
name = (TextView) convertView.findViewById(R.id.list_contactName);
name.setText(user.getFirstName() + " " + user.getLastName());
industry = (TextView) convertView.findViewById(R.id.list_industry);
industry.setText(user.getIndustry());
logo = (ImageView) convertView.findViewById(R.id.list_logo);
break;
case TYPE_SEPARATOR:
TextView seperator = (TextView) mInflater.inflate(R.layout.list_header, null);
seperator.setText(mData.get(position).toString());
seperator.setClickable(false);
seperator.setBackgroundColor(mContext.getResources().getColor(R.color.blue));
convertView = seperator;
break;
}
return convertView;
}
/********************* SectionIndexer Methods ***********************/
#Override
public Object[] getSections() {
return sections;
}
#Override
public int getPositionForSection(int sectionIndex) {
return mapIndex.get(sections[sectionIndex]);
}
#Override
public int getSectionForPosition(int position) {
return 0;
}
}
public class ContactListActivity extends AppCompatActivity {
private ArrayList<UserModel> mUserList;
private ListAdapter adapter;
private IndexableListView mListView;
public static final String CONTACT_FRAGMENT = "ContactFragment";
#Override
public void onCreate(Bundle savedInstances) {
super.onCreate(savedInstances);
setContentView(R.layout.list_layout);
//setHasOptionsMenu(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mUserList = UserList.get(this).getUserList();
Collections.sort(mUserList, UserModel.Comparators.NAME);
mListView = (IndexableListView) findViewById(R.id.listview);
adapter = new ListAdapter(this, mUserList);
mListView.setAdapter(adapter);
mListView.setFastScrollEnabled(true);
mListView.setDivider(null);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (adapter.getItemViewType(position) == adapter.TYPE_ITEM) {
Intent intent = new Intent(view.getContext(), ContactActivity.class);
intent.putExtra(HomeFragment.LAUNCH_FRAGMENT, CONTACT_FRAGMENT);
intent.putExtra("userId", adapter.getRealPosition(position));
startActivity(intent);
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.sort_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.sortName){
Log.d("Sort ", "Sort by Name Clicked");
}
return super.onOptionsItemSelected(item);
}
}
12-10 09:47:39.951 17995-17995/com.example.macintosh.klickcard D/ListAdapter: getRealPosition: Key = 6Value = null
12-10 09:47:39.971 17995-17995/com.example.macintosh.klickcard D/AndroidRuntime: Shutting down VM
12-10 09:47:39.981 17995-17995/com.example.macintosh.klickcard E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.macintosh.klickcard, PID: 17995
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
at com.example.macintosh.klickcard.Helpers.ListAdapter.getRealPosition(ListAdapter.java:83)
at com.example.macintosh.klickcard.ContactListActivity$1.onItemClick(ContactListActivity.java:52)
at android.widget.AdapterView.performItemClick(AdapterView.java:339)
at android.widget.AbsListView.performItemClick(AbsListView.java:1544)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3721)
at android.widget.AbsListView$3.run(AbsListView.java:5660)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6837)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
You are creating new View element in your ListAdapter getView method every time, that might be the reason of crash. You can make use of previously created view element.
public View getView(int position, View convertView, ViewGroup parent) {
// Create view element only if convertView is null
if (convertView == null) {
LayoutInflater inflater = context.getLayoutInflater();
convertView= inflater.inflate(YOUR_XML_RESOURCE_ID, parent, false);
}
// Populate convertView with necessary details
return convertView;
}
It took me a while to figure this out. Couple of things I found out was that don't check if convert view is null, because it messes up the organization of the list. Second was not to use a hashmap because the adapter class gets called in random times and you are mapping to wrong positions hence the null pointer exception. The trick is this method. Nothing mind blowing just a plain index shift.
public int getRealPosition(int key){
user = (UserModel) getItem(key);
String ch = user.getFirstName().substring(0,1);
for (int i = 0; i < sections.length; i++) {
if (ch.equalsIgnoreCase(sections[i])) {
return key - (i + 1);
}
}
return -1;
}

How to Retrieve Name | Value pair in Listview for Multiple Checked Items?

My list view is working fine and populating all items from cursor.
i need to assign get the id of the assigned name in the list view.
I am using multiple check boxes to select items from list view.
How can i get the Name|Value pair from listview for selected items?.
ListView listView;
ArrayAdapter<String> adapter;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
try
{
super.onCreate(savedInstanceState);
setContentView(R.layout.servicelist_item);
//String[] sports ;
//get jobtype
Cursor cur=dbHelper.fetchByJobNumber(stringJobnumber);
String cur_type;
cur_type=cur.getString(18);
//passing jobtype to fetch service items through cursor
Cursor cursor=dbHelper.fetchItemsByType(cur_type);
ArrayList<String> sports=new ArrayList<String>();
if (cursor.moveToFirst())
{
do
{
//assigning cursor items to arraylist variable sports
/* assigning item name to list view*/
/*My cursor holds name value pair */
sports.add(cursor.getString(3));
}
while (cursor.moveToNext());
}
//setting array adapter to populate listView
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_multiple_choice, sports);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setAdapter(adapter);
button.setOnClickListener(this);
}
catch(Exception e)
{
System.out.println(e);
}
}
//Onclick method
public void onClick(View v)
{
SparseBooleanArray checked = listView.getCheckedItemPositions();
ArrayList<String> selectedItems = new ArrayList<String>();
for (int i = 0; i < checked.size(); i++)
{
// Item position in adapter
int position = checked.keyAt(i);
// Add sport if it is checked i.e.) == TRUE!
if (checked.valueAt(i))
selectedItems.add(adapter.getItem(position));
}
final String[] outputStrArr = new String[selectedItems.size()];
Log.e("selectedItems.size()====>>", ""+selectedItems.size());
for (int i = 0; i < selectedItems.size(); i++)
{
Log.e("selectedItems====>>", ""+selectedItems.get(i));
outputStrArr[i] = selectedItems.get(i);
}
}
Looking at your code, I would create an object that holds your name and id:
public class Sport {
private String id;
private String name;
public Sport(String id, String name){
this.id = id;
this.name = name;
}
public String getId(){
return id;
}
public String getName(){
return name;
}
}
I have often needed this feature, so what I did was create a custom adapter that has a String[] of ids, and List<T> for your data, and a map <String, T>. Doing this gives your list a few nice features like accessing by id and position. Where this adapter will maintain 3 instances of data, I recommend only using it for lists that are relatively smaller (less than 100).
Here is the adapter I like to use:
public abstract class MappedAdapter<T> extends BaseAdapter{
private Context mContext;
private Map<String, T> mMap;
private ArrayList<String> mIdList;
public MappedAdapter(Context context, ArrayList<T> arrayList) {
this.mContext = context;
mMap = new HashMap<>();
mIdList = new ArrayList<>();
for (T object : arrayList) {
add(object);
}
}
public MappedAdapter(Context context, T[] arrayList){
this.mContext = context;
mMap = new HashMap<>();
mIdList = new ArrayList<>();
for (T object : arrayList) {
add(object);
}
}
public abstract String getObjectId(T object);
public abstract String getObjectString(T object);
public T getObject(int position) {
return mMap.get(mIdList.get(position));
}
public String getObjectId(int position){
return mIdList.get(position);
}
public boolean add(T object) {
final String id = getObjectId(object);
if(!mMap.containsKey(id)){
mIdList.add(id);
mMap.put(id, object);
this.notifyDataSetChanged();
return true;
}
return false;
}
public void remove(T object){
final String id = getObjectId(object);
mIdList.remove(id);
mMap.remove(id);
this.notifyDataSetChanged();
}
#SuppressWarnings("unchecked")
public Map.Entry<String, T> getEntry(int position){
HashMap<String, T> entry = new HashMap<>();
String key = mIdList.get(position);
entry.put(key, mMap.get(key));
return (Map.Entry<String, T>) entry;
}
#Override
public int getCount() {
return mMap.size();
}
#Override
public Object getItem(int position) {
return mMap.get(mIdList.get(position));
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
T object = mMap.get(mIdList.get(position));
if (view == null) {
int layoutResource = android.R.layout.simple_list_item_1;
view = LayoutInflater.from(mContext).inflate(layoutResource, null);
}
TextView tv = (TextView) view.findViewById(android.R.id.text1);
tv.setText(getObjectString(object));
return view;
}
}
This is an adapter class I use a lot that you just pass in a list, and you can access it by id and position. And will not allow for duplicate objects. It takes a generic so you can use this for many different objects.
This will ask you to override two methods:
getObjectId() Object id is what it will use as the id/key to build the map.
getObjectString() The objectString is what string you want to display in the list view
By default this will be using android.R.layout.simple_list_item_1 for its layout. Obviously, you can change this, or better yet, build a sub class and override the getView()
Usage:
MappedAdapter<Sport> mappedAdapter = new MappedAdapter<Sport>(context, sports){
#Override
public String getObjectId(Sport object) {
return object.getId();
}
#Override
public String getObjectString(Sport object) {
return object.getName();
}
};
ListView listView = ... ;
listView.setAdapter(mappedAdapter);
To get your Key|Value pair, you can get it by position :
Map.Entry<String, Sport> entry = mappedAdapter.getEntry(positon);
String key = entry.getKey();
Sport sport = entry.getValue();
Let me know if you need any clarification. Happy to help.

How to apply filter to customlistview

I am using Custom adapter for my listview and I want to apply filter for searching perticular item from the list how to do that? I Know that how to do that for adapter extending ArrayAdapter but in my case it is simplesectionadapter.I have one editText above the listview from the text entered in the edittext I want to serch the Item.
Collections.sort(contents, new Comparator<CategoryPojo>() {
#Override
public int compare(CategoryPojo s1, CategoryPojo s2) {
return s1.getCategoryName().compareToIgnoreCase(
s2.getCategoryName());
}
});
final CategoryAdapter adapter = new CategoryAdapter(this,
android.R.layout.simple_list_item_1, contents);
Sectionizer<CategoryPojo> alphabetSectionizer = new Sectionizer<CategoryPojo>() {
#Override
public String getSectionTitleForItem(CategoryPojo instance) {
return instance.getCategoryName().substring(0, 1);
}
};
final SimpleSectionAdapter<CategoryPojo> sectionAdapter = new SimpleSectionAdapter<CategoryPojo>(
this, adapter, R.layout.section_header, R.id.title,
alphabetSectionizer);
listView.setFastScrollEnabled(true);
listView.setTextFilterEnabled(true);
listView.setAdapter(sectionAdapter);
and this is simplesectionadapter
public class SimpleSectionAdapter<T> extends BaseAdapter implements Filterable{
static final boolean DEBUG = false;
static final String TAG = SimpleSectionAdapter.class.getSimpleName();
// Constants
private static final int VIEW_TYPE_SECTION_HEADER = 0;
// Attributes
private Context mContext;
private BaseAdapter mListAdapter;
private int mSectionHeaderLayoutId;
private int mSectionTitleTextViewId;
private Sectionizer<T> mSectionizer;
private LinkedHashMap<String, Integer> mSections;
AlphabetIndexer alphaIndexer;
private Filter filter;
/**
* Constructs a {#linkplain SimpleSectionAdapter}.
*
* #param context The context for this adapter.
* #param listAdapter A {#link ListAdapter} that has to be sectioned.
* #param sectionHeaderLayoutId Layout Id of the layout that is to be used for the header.
* #param sectionTitleTextViewId Id of a TextView present in the section header layout.
* #param sectionizer Sectionizer for sectioning the {#link ListView}.
*/
public SimpleSectionAdapter(Context context, BaseAdapter listAdapter,
int sectionHeaderLayoutId, int sectionTitleTextViewId,
Sectionizer<T> sectionizer) {
if(context == null) {
throw new IllegalArgumentException("context cannot be null.");
} else if(listAdapter == null) {
throw new IllegalArgumentException("listAdapter cannot be null.");
} else if(sectionizer == null) {
throw new IllegalArgumentException("sectionizer cannot be null.");
} else if(!isTextView(context, sectionHeaderLayoutId, sectionTitleTextViewId)) {
throw new IllegalArgumentException("sectionTitleTextViewId should be a TextView.");
}
this.mContext = context;
this.mListAdapter = listAdapter;
this.mSectionHeaderLayoutId = sectionHeaderLayoutId;
this.mSectionTitleTextViewId = sectionTitleTextViewId;
this.mSectionizer = sectionizer;
this.mSections = new LinkedHashMap<String, Integer>();
// Find sections
findSections();
}
private boolean isTextView(Context context, int layoutId, int textViewId) {
View inflatedView = View.inflate(context, layoutId, null);
View foundView = inflatedView.findViewById(textViewId);
return foundView instanceof TextView;
}
#Override
public int getCount() {
return mListAdapter.getCount() + getSectionCount();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
SectionHolder sectionHolder = null;
switch (getItemViewType(position)) {
case VIEW_TYPE_SECTION_HEADER:
if(view == null) {
view = View.inflate(mContext, mSectionHeaderLayoutId, null);
sectionHolder = new SectionHolder();
sectionHolder.titleTextView = (TextView) view.findViewById(mSectionTitleTextViewId);
view.setTag(sectionHolder);
} else {
sectionHolder = (SectionHolder) view.getTag();
}
break;
default:
view = mListAdapter.getView(getIndexForPosition(position),
convertView, parent);
break;
}
if(sectionHolder != null) {
String sectionName = sectionTitleForPosition(position);
sectionHolder.titleTextView.setText(sectionName);
}
return view;
}
#Override
public boolean areAllItemsEnabled() {
return mListAdapter.areAllItemsEnabled() ?
mSections.size() == 0 : false;
}
#Override
public int getItemViewType(int position) {
int positionInCustomAdapter = getIndexForPosition(position);
return mSections.values().contains(position) ?
VIEW_TYPE_SECTION_HEADER :
mListAdapter.getItemViewType(positionInCustomAdapter) + 1;
}
#Override
public int getViewTypeCount() {
return mListAdapter.getViewTypeCount() + 1;
}
#Override
public boolean isEnabled(int position) {
return mSections.values().contains(position) ?
false : mListAdapter.isEnabled(getIndexForPosition(position));
}
#Override
public Object getItem(int position) {
return mListAdapter.getItem(getIndexForPosition(position));
}
#Override
public long getItemId(int position) {
return mListAdapter.getItemId(getIndexForPosition(position));
}
#Override
public void notifyDataSetChanged() {
mListAdapter.notifyDataSetChanged();
findSections();
super.notifyDataSetChanged();
}
/**
* Returns the actual index of the object in the data source linked to the this list item.
*
* #param position List item position in the {#link ListView}.
* #return Index of the item in the wrapped list adapter's data source.
*/
public int getIndexForPosition(int position) {
int nSections = 0;
Set<Entry<String, Integer>> entrySet = mSections.entrySet();
for(Entry<String, Integer> entry : entrySet) {
if(entry.getValue() < position) {
nSections++;
}
}
return position - nSections;
}
static class SectionHolder {
public TextView titleTextView;
}
private void findSections() {
int n = mListAdapter.getCount();
int nSections = 0;
mSections.clear();
for(int i=0; i<n; i++) {
String sectionName = mSectionizer.getSectionTitleForItem((T) mListAdapter.getItem(i));
if(!mSections.containsKey(sectionName)) {
mSections.put(sectionName, i + nSections);
nSections ++;
}
}
if(DEBUG) {
Log.d(TAG, String.format("Found %d sections.", mSections.size()));
}
}
private int getSectionCount() {
return mSections.size();
}
private String sectionTitleForPosition(int position) {
String title = null;
Set<Entry<String, Integer>> entrySet = mSections.entrySet();
for(Entry<String, Integer> entry : entrySet) {
if(entry.getValue() == position) {
title = entry.getKey();
break;
}
}
return title;
}
You can use addTextChangedListener & in onTextChanged method get your search string & match this string with your listItems & prepare new list of searched items.Then reinitialize your adapter & set it to ListView.

Categories

Resources