custom row in a listPreference? - android

I am trying to create a ListPreference but somehow disable one of the items. Sort of like gray it out or something and not have the ability to choose it. It will be an upcoming feature and I want it to be in the list just not selectable.
I have created a custom ListPreference class and in that class a custom adapter, hoping to use the adapter to create what I want.
The code works, and it sets the adapter, but none of the adapter functions get called. I set breakpoints on the methods, such as getCount() but they never get called.
Here's my code. Custom ListPreference taken from http://blog.350nice.com/wp/archives/240
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.preference.ListPreference;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.app.AlertDialog.Builder;
public class CustomListPreference extends ListPreference {
private boolean[] mClickedDialogEntryIndices;
CustomListPreferenceAdapter customListPreferenceAdapter = null;
Context mContext;
public CustomListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mClickedDialogEntryIndices = new boolean[getEntries().length];
}
#Override
protected void onPrepareDialogBuilder(Builder builder) {
CharSequence[] entries = getEntries();
CharSequence[] entryValues = getEntryValues();
if (entries == null || entryValues == null
|| entries.length != entryValues.length) {
throw new IllegalStateException(
"ListPreference requires an entries array "
+"and an entryValues array which are both the same length");
}
builder.setMultiChoiceItems(entries, mClickedDialogEntryIndices,
new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog, int which,
boolean val) {
mClickedDialogEntryIndices[which] = val;
}
});
// setting my custom list adapter
customListPreferenceAdapter = new CustomListPreferenceAdapter(mContext);
builder.setAdapter(customListPreferenceAdapter, null);
}
private class CustomListPreferenceAdapter extends BaseAdapter {
public CustomListPreferenceAdapter(Context context) {}
public int getCount() {
return 1;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
convertView.setBackgroundColor(Color.BLUE);
return convertView;
}
}
}

OK I got this to work, mostly. I had to use a custom defined class that extends ListPreference. Then inside of that I had to create a custom adapter class just like you would for a ListView and set it to the builder using builder.setAdapter(). I also had to define listeners for both the RadioButtons and the ListView rows that handled unchecking of the RadioButtons and such. The only issues I still have are, my custom ListPreference has both an OK and a Cancel button where a ListPreference only has the cancel button. I don't know how to remove the OK button. Also, I can't get the rows to highlight when I click on them like they do in a regular ListPreference.
The java code for the custom ListPreference class. Be sure to mind things like your package name, the preference name (key), your entries and values for the ListPreference, and the names of your xml items.
package your.package.here;
import java.util.ArrayList;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.preference.ListPreference;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CompoundButton;
import android.widget.RadioButton;
import android.widget.TextView;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
public class CustomListPreference extends ListPreference
{
CustomListPreferenceAdapter customListPreferenceAdapter = null;
Context mContext;
private LayoutInflater mInflater;
CharSequence[] entries;
CharSequence[] entryValues;
ArrayList<RadioButton> rButtonList;
SharedPreferences prefs;
SharedPreferences.Editor editor;
public CustomListPreference(Context context, AttributeSet attrs)
{
super(context, attrs);
mContext = context;
mInflater = LayoutInflater.from(context);
rButtonList = new ArrayList<RadioButton>();
prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
editor = prefs.edit();
}
#Override
protected void onPrepareDialogBuilder(Builder builder)
{
entries = getEntries();
entryValues = getEntryValues();
if (entries == null || entryValues == null || entries.length != entryValues.length )
{
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array which are both the same length");
}
customListPreferenceAdapter = new CustomListPreferenceAdapter(mContext);
builder.setAdapter(customListPreferenceAdapter, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
}
});
}
private class CustomListPreferenceAdapter extends BaseAdapter
{
public CustomListPreferenceAdapter(Context context)
{
}
public int getCount()
{
return entries.length;
}
public Object getItem(int position)
{
return position;
}
public long getItemId(int position)
{
return position;
}
public View getView(final int position, View convertView, ViewGroup parent)
{
View row = convertView;
CustomHolder holder = null;
if(row == null)
{
row = mInflater.inflate(R.layout.custom_list_preference_row, parent, false);
holder = new CustomHolder(row, position);
row.setTag(holder);
// do whatever you need here, for me I wanted the last item to be greyed out and unclickable
if(position != 3)
{
row.setClickable(true);
row.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
for(RadioButton rb : rButtonList)
{
if(rb.getId() != position)
rb.setChecked(false);
}
int index = position;
int value = Integer.valueOf((String) entryValues[index]);
editor.putInt("yourPref", value);
Dialog mDialog = getDialog();
mDialog.dismiss();
}
});
}
}
return row;
}
class CustomHolder
{
private TextView text = null;
private RadioButton rButton = null;
CustomHolder(View row, int position)
{
text = (TextView)row.findViewById(R.id.custom_list_view_row_text_view);
text.setText(entries[position]);
rButton = (RadioButton)row.findViewById(R.id.custom_list_view_row_radio_button);
rButton.setId(position);
// again do whatever you need to, for me I wanted this item to be greyed out and unclickable
if(position == 3)
{
text.setTextColor(Color.LTGRAY);
rButton.setClickable(false);
}
// also need to do something to check your preference and set the right button as checked
rButtonList.add(rButton);
rButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if(isChecked)
{
for(RadioButton rb : rButtonList)
{
if(rb != buttonView)
rb.setChecked(false);
}
int index = buttonView.getId();
int value = Integer.valueOf((String) entryValues[index]);
editor.putInt("yourPref", value);
Dialog mDialog = getDialog();
mDialog.dismiss();
}
}
});
}
}
}
}
The xml for my PreferenceActivity. This is not my full xml, took out all my other preference items for simplicity. Again, be sure to mind the package name, the custom ListPreference class must be referenced by the package name. Also mind the names of the preference and the array names that hold the entries and values.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Your Title">
<your.package.here.CustomListPreference
android:key="yourPref"
android:title="Your Title"
android:dialogTitle="Your Title"
android:summary="Your Summary"
android:defaultValue="1"
android:entries="#array/yourArray"
android:entryValues="#array/yourValues"/>
</PreferenceCategory>
</PreferenceScreen>
My xml for the dialog's list view row. In the getView method be sure to use the name of this xml file in the line that inflates this.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="8dip"
android:paddingTop="8dip"
android:paddingLeft="10dip"
android:paddingRight="10dip">
<TableLayout
android:id="#+id/custom_list_view_row_table_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="0">
<TableRow
android:id="#+id/custom_list_view_row_table_row"
android:gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/custom_list_view_row_text_view"
android:textSize="22sp"
android:textColor="#000000"
android:gravity="center_vertical"
android:layout_width="160dip"
android:layout_height="40dip" />
<RadioButton
android:checked="false"
android:id="#+id/custom_list_view_row_radio_button"/>
</TableRow>
</TableLayout>
</LinearLayout>
Finally, under res/values here is my array.xml that contains the entry names and values for the ListPreference. Again, shortened mine for simplicity.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="yourArray">
<item>Item 1</item>
<item>Item 2</item>
<item>Item 3</item>
<item>Item 4</item>
</string-array>
<string-array name="yourValues">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
</string-array>
</resources>

This worked well for me. I used an Adapter approach that injects a wrapped adapter into the view.
Here is the base wrapped adapter class:
import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.WrapperListAdapter;
class ListPrefWrapperAdapter implements WrapperListAdapter {
private ListAdapter mOrigAdapter;
public ListPrefWrapperAdapter(ListAdapter origAdapter) {
mOrigAdapter = origAdapter;
}
#Override
public ListAdapter getWrappedAdapter() {
return mOrigAdapter;
}
#Override
public boolean areAllItemsEnabled() {
return getWrappedAdapter().areAllItemsEnabled();
}
#Override
public boolean isEnabled(int position) {
return getWrappedAdapter().isEnabled(position);
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
getWrappedAdapter().registerDataSetObserver(observer);
}
#Override
public void unregisterDataSetObserver(DataSetObserver observer) {
getWrappedAdapter().unregisterDataSetObserver(observer);
}
#Override
public int getCount() {
return getWrappedAdapter().getCount();
}
#Override
public Object getItem(int position) {
return getWrappedAdapter().getItem(position);
}
#Override
public long getItemId(int position) {
return getWrappedAdapter().getItemId(position);
}
#Override
public boolean hasStableIds() {
return getWrappedAdapter().hasStableIds();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getWrappedAdapter().getView(position, convertView, parent);
}
#Override
public int getItemViewType(int position) {
return getWrappedAdapter().getItemViewType(position);
}
#Override
public int getViewTypeCount() {
return getWrappedAdapter().getViewTypeCount();
}
#Override
public boolean isEmpty() {
return getWrappedAdapter().isEmpty();
}
}
Here is the CustomListPreference base class that uses the ListPrefWrapperAdapter:
import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.widget.ListAdapter;
import android.widget.ListView;
public class CustomListPreference extends ListPreference {
public CustomListPreference(Context context) {
super(context);
}
public CustomListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void showDialog(Bundle state) {
super.showDialog(state);
AlertDialog dialog = (AlertDialog) getDialog();
ListView listView = dialog.getListView();
ListAdapter adapter = listView.getAdapter();
final ListPrefWrapperAdapter fontTypeAdapter = createWrapperAdapter(adapter);
// Adjust the selection because resetting the adapter loses the selection.
int selectedPosition = findIndexOfValue(getValue());
listView.setAdapter(fontTypeAdapter);
if (selectedPosition != -1) {
listView.setItemChecked(selectedPosition, true);
listView.setSelection(selectedPosition);
}
}
protected ListPrefWrapperAdapter createWrapperAdapter(ListAdapter origAdapter) {
return new ListPrefWrapperAdapter(origAdapter);
}
}
Finally, here are the derived classes that do the disabling and enabling of specific rows:
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckedTextView;
import android.widget.ListAdapter;
public class FontTypePreference extends CustomListPreference {
public FontTypePreference(Context context) {
super(context);
}
public FontTypePreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected ListPrefWrapperAdapter createWrapperAdapter(ListAdapter origAdapter) {
return new Adapter(origAdapter);
}
private class Adapter extends ListPrefWrapperAdapter {
private static final float TEXT_SIZE = 25.0f;
private static final int STARTING_UPGRADE_REQUIRED_INDEX = 8;
public Adapter(ListAdapter origAdapter) {
super(origAdapter);
}
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
return position < STARTING_UPGRADE_REQUIRED_INDEX;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
CheckedTextView textView = (CheckedTextView) getWrappedAdapter()
.getView(position, convertView, parent);
textView.setTextColor(position < STARTING_UPGRADE_REQUIRED_INDEX ?
Color.BLACK : Color.RED);
return textView;
}
}
}
I have only tested this code on SDK version 15 and above.

Probably have to add editor.commit(); after each editor.putInt(...)

function getcount() returns is wrong.
public int getCount()
{
return entries.length;
}
public Object getItem(int position)
{
return null;
}
public long getItemId(int position)
{
return position;
}

Thanks Bob for that answer, and Vamsi for trying to correct the duplicate entries bug, but Vamsi's fix didn't work for me. I had to keep an array of views and return it on the position if it had already been created before. So here is my full CustomListPreferenceAdapter class. It also contains the fix to check the selected preference value.
private class CustomListPreferenceAdapter extends BaseAdapter
{
View[] Views;
public CustomListPreferenceAdapter(Context context)
{
Views = new View[entries.length];
}
public int getCount()
{
return entries.length;
}
public Object getItem(int position)
{
return null;
}
public long getItemId(int position)
{
return position;
}
public View getView(final int position, View convertView, ViewGroup parent)
{
View row = Views[position];
CustomHolder holder = null;
if(row == null)
{
row = mInflater.inflate(R.layout.listrow, parent, false);
holder = new CustomHolder(row, position);
row.setTag(holder);
Views[position] = row;
}
return row;
}
class CustomHolder
{
private TextView text = null;
private RadioButton rButton = null;
CustomHolder(View row, int position)
{
text = (TextView)row.findViewById(R.id.custom_list_view_row_text_view);
text.setText(entries[position]);
rButton = (RadioButton)row.findViewById(R.id.custom_list_view_row_radio_button);
rButton.setId(position);
if(getPersistedString("").compareTo((String)entryValues[position])==0)
rButton.setChecked(true);
rButtonList.add(rButton);
}
}
}

I think you can achieve exactly what you want by setting the enabled flag of the ListPreference to false:
ListPreference lp = (ListPreference) findPreference("YOUR_KEY");
lp.setEnabled(false);
This grays out the description and makes it not selectable.

modified the code as below -
if(row == null) {
row = mInflater.inflate(R.layout.custom_list_preference_row, parent, false);
holder = new CustomHolder(row, position);
} else {
holder = row.getTag()
}
// update the holder with new Text/Drawables etc.,
row.setTag(holder);
return row;
PS - NidhiGondhia requested for modified code, as in the comments this can not be fit, updating the modified code here.

You can do it more easily.
Steps:
Extend ListPreference
public class CustomListPreference extends ListPreference
{
Context mContext;
public CustomListPreference(Context context, AttributeSet attrs)
{
super(context, attrs);
mContext = context;
}
}
Override onPrepareDialogBuilder and replace mBuilder in DialogPreference with ProxyBuilder:
#Override
protected void onPrepareDialogBuilder(android.app.AlertDialog.Builder builder){
super.onPrepareDialogBuilder(builder);
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.FROYO) {
return;
}
// Inject Builder Proxy for intercepting of getView.
try {
Field privateBuilderField =
DialogPreference.class.getDeclaredField("mBuilder");
privateBuilderField.setAccessible(true);
privateBuilderField.set(this, new ProxyBuilder(mContext, (android.app.AlertDialog.Builder)privateBuilderField.get(this)));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
Handle getView in ProxyBuilder->AlertDialog->onShow->getListView->Adapter
private class ProxyBuilder extends android.app.AlertDialog.Builder{
android.app.AlertDialog.Builder mBuilder;
private ProxyBuilder(Context context, AlertDialog.Builder builder) {
super(context);
mBuilder = builder;
}
#TargetApi(Build.VERSION_CODES.FROYO)
#Override
public AlertDialog create() {
AlertDialog alertDialog = mBuilder.create();
alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
ListView listView = ((AlertDialog)dialog).getListView();
final ListAdapter originalAdapter = listView.getAdapter();
listView.setAdapter(new ListAdapter(){
#Override
public int getCount() {
return originalAdapter.getCount();
}
#Override
public Object getItem(int id) {
return originalAdapter.getItem(id);
}
#Override
public long getItemId(int id) {
return originalAdapter.getItemId(id);
}
#Override
public int getItemViewType(int id) {
return originalAdapter.getItemViewType(id);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = originalAdapter.getView(position, convertView, parent);
TextView textView = (TextView)view;
textView.setTextColor(Color.RED);
return view;
}
#Override
public int getViewTypeCount() {
return originalAdapter.getViewTypeCount();
}
#Override
public boolean hasStableIds() {
return originalAdapter.hasStableIds();
}
#Override
public boolean isEmpty() {
return originalAdapter.isEmpty();
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
originalAdapter.registerDataSetObserver(observer);
}
#Override
public void unregisterDataSetObserver(DataSetObserver observer) {
originalAdapter.unregisterDataSetObserver(observer);
}
#Override
public boolean areAllItemsEnabled() {
return originalAdapter.areAllItemsEnabled();
}
#Override
public boolean isEnabled(int position) {
return originalAdapter.isEnabled(position);
}
});
}
});
return alertDialog;
}
}

This worked for me, but it did not work well if the list does not fit on the screen (and requires scrolling). It took me a loooong time to find the solution (but I finally did).
First the problem:
As described here: getView called with wrong position when scrolling fast you will get unpredictable behavior when you use an onclick listener in:
public View getView(final int position, View convertView, ViewGroup parent)
In my case, the onClick event would be stored in memory and would be executed when the user tried to scroll (slightly).
And now the solution:
Put the onClick listener in the main class (at least this worked for me):
public class CustomListPreference extends ListPreference {
// Other code (see above)
#Override
protected void onPrepareDialogBuilder(Builder builder)
{
builder.setPositiveButton(null, null);
entries = getEntries();
entryValues = getEntryValues();
if (entries == null || entryValues == null || entries.length != entryValues.length )
{
throw new IllegalStateException("ListPreference requires an entries array and an entryValues array which are both the same length");
}
customListPreferenceAdapter = new CustomListPreferenceAdapter(mContext);
builder.setAdapter(customListPreferenceAdapter, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int position)
{
// Code here, using position to indicate the row that was clicked...
dialog.dismiss();
}
});
}
Spend waaaay too much time on this, so hope it will help someone out :)
All in all, still really happy with this code example! (use it as a color picker).
P.S. If you like this post, please vote useful. Thx!

Related

How to get gridview multiple positions and store into array variable

Now I am displaying images in grid-view, it working fine. In that grid-view i am going to select few images, i want store selected multiple images position in array variable (example: if i select position 1, 4 ,10. i want that particular position id and i want to store it array like 1,4,10,15,). I will put my activity and adapter code below. Thank you in advance.
Activity
public class EM_event_total_userSeats extends AppCompatActivity implements RestCallback,AdapterView.OnItemClickListener {
String user_id,first_name,last_name,name,emailid,contact_no,gender1,date_of_birth,country_id,postal_code,rolename,profession_response,Street_Address,City,photo;
GridView GridUserSeats;
;
TextView textView1,textView2,Tvposition;
ImageView Ivseats;
public static EM_event_total_userseatsAdapter adapter;
ArrayList<EM_event_total_UserSeatsModel> EMeventuserseatslist;
View savedView;
View previous = null;
String event_id = "EVEPRI62";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.em_event_total_user_seats);
initviews();
callSeatsApi();
GridUserSeats.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
String a = String.valueOf(position);
Toast.makeText(EM_event_total_userSeats.this, a + "#Selected", Toast.LENGTH_SHORT).show();
v.setBackgroundColor(Color.GREEN);
adapter.notifyDataSetChanged();
}
});
}
private void initviews() {
GridUserSeats=(GridView)findViewById(R.id.GridUserSeats);
GridUserSeats.setOnItemClickListener(this);
textView1=(TextView) findViewById(R.id.textView1);
// textView2=(TextView) findViewById(R.id.textView2);
Intent intent = getIntent();
first_name = intent.getStringExtra("first_name");
last_name = intent.getStringExtra("last_name");
}
private void callSeatsApi() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("events", event_id);
RestService.getInstance(EM_event_total_userSeats.this).getUserSeats(map, new MyCallback<ArrayList<EM_event_total_UserSeatsModel>>(EM_event_total_userSeats.this,
EM_event_total_userSeats.this, true, "Finding seats....", GlobalVariables.SERVICE_MODE.EM_SEATS));
}
#Override
public void onFailure(Call call, Throwable t, GlobalVariables.SERVICE_MODE mode) {
}
#Override
public void onSuccess(Response response, GlobalVariables.SERVICE_MODE mode)
{
switch (mode)
{
case EM_SEATS:
EMeventuserseatslist = (ArrayList<EM_event_total_UserSeatsModel>)response.body();
adapter = new EM_event_total_userseatsAdapter(EMeventuserseatslist, getApplicationContext());
GridUserSeats.setAdapter(adapter);
break;
}
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
}
Adapter
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
import cfirst.live.com.R;
import cfirst.live.com.model.BasketModel;
import cfirst.live.com.model.EM_event_total_UserSeatsModel;
public class EM_event_total_userseatsAdapter extends ArrayAdapter<EM_event_total_UserSeatsModel> implements View.OnClickListener {
ArrayList<EM_event_total_UserSeatsModel> dataSet;
public ArrayList<EM_event_total_UserSeatsModel> EMeventuserseatslist = new ArrayList<EM_event_total_UserSeatsModel>();
Context mContext;
ViewHolder holder;
String user_seats;
private int[] tagCollection;
private String[] mobileValues;
private String[] mobileValuesD;
private static class ViewHolder {
TextView TvEmUserSeats;
ImageView IvUsreSeats,available,selctedimag;
}
private String[] strings;
List<Integer> selectedPositions = new ArrayList<>();
public EM_event_total_userseatsAdapter(ArrayList<EM_event_total_UserSeatsModel> data, Context context) {
super(context, R.layout.list_em_get_seats, data);
this.dataSet = data;
this.mContext=context;
}
public int getTagFromPosition(int position) {
return tagCollection[position];
}
#Override
public void onClick(View v) {
int position=(Integer) v.getTag();
Object object= getItem(tagCollection[position]);
EM_event_total_UserSeatsModel dataModel=(EM_event_total_UserSeatsModel) object;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
EM_event_total_UserSeatsModel dataModel = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.list_em_get_seats, parent, false);
viewHolder.TvEmUserSeats = (TextView) convertView.findViewById(R.id.TvEmUserSeats);
viewHolder.IvUsreSeats = (ImageView) convertView.findViewById(R.id.IvUsreSeats);
result=convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result=convertView;
}
String blue_available = "seat3.png";
String red_booked = "seat1.png";
String get_seat = dataModel.getBookedStatus();
viewHolder.TvEmUserSeats.setText(dataModel.getSeatName());
if(Integer.parseInt(get_seat) == 1){
Picasso.with(mContext).load("imageurl + red_booked).into(viewHolder.IvUsreSeats);
}else
{
Picasso.with(mContext).load("imageurl + blue_available).into(viewHolder.IvUsreSeats);
}
return convertView;
}
}
It's simple. You can use SparseBooleanArray for this purpose. Just add the following methods as is in your adapter:
public void toggleSelection(int item) {
if (selectedItems.get(item, false)) {
selectedItems.delete(item);
} else {
selectedItems.put(item, true);
}
notifyDataSetChanged();
}
public void setSelectedItems(List<Object> objects) {
if (objects != null) {
for (Object object : objects) {
toggleSelection(object.getId());
}
notifyDataSetChanged();
}
}
public void clearSelections() {
selectedItems.clear();
notifyDataSetChanged();
}
public int getSelectedItemCount() {
return selectedItems.size();
}
public List<Integer> getSelectedItems() {
List<Integer> items =
new ArrayList<Integer>(selectedItems.size());
for (int i = 0; i < selectedItems.size(); i++) {
items.add(selectedItems.keyAt(i));
}
return items;
}
Use the set selection method to store the selected status of your item.
Don't forget to initialize SparseBooleanArray in your constructor.
SparseBooleanArray SparseBooleanArray = new SparseBooleanArray();
After that, use toggleSelection(position); to change the selected status of an item, then after performing selections, call getSelectedItem() to get the selected items in an array.
// create an Arraylist and add the selected position in a list
List <int> selectedArray = new ArrayList<>();
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int click = (int) parent.getItemAtPosition(position);
selectedArray.add(click);
}

Unable to get actual position of item after filtering ListView

Here is my MainActivity.java where I define an OnClickListener on the items. Here I am always getting a wrong value of the item after filtering.
If there are 10 items in the ListView then after filtering if I get 3 items and the correct position is like 3,6,9 then I am getting 0,1,2 instead.
package com.focusmedica.maadiabetes;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import java.util.ArrayList;
public class MainActivity extends Activity {
private MainAdapter adapter;
private static ListView lvFiltered;
private static ArrayList<DataModel> data=new ArrayList<>();;
MyDatabase handler;
private EditText etSearch;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvFiltered =(ListView)findViewById(R.id.lvFiltered);
etSearch = (EditText)findViewById(R.id.etSearch);
etSearch.setText("");
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
handler=new MyDatabase(this);
data=handler.getChapterDetails();
adapter = new MainAdapter(this,data);
lvFiltered.setAdapter(adapter);
lvFiltered.setTextFilterEnabled(true);
lvFiltered.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(MainActivity.this, SubActivity.class);
intent.putExtra("position", position);
startActivity(intent);
}
});
etSearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
if(cs.length()>0) {
etSearch.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.delete, 0);
}else{
etSearch.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
// When user changed the Text
adapter.getFilter().filter(cs);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
etSearch.setOnTouchListener(new View.OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP) {
if(etSearch.getCompoundDrawables()[2]!=null){
if(event.getX() >= (etSearch.getRight()- etSearch.getLeft() - etSearch.getCompoundDrawables()[2].getBounds().width())) {
etSearch.setText("");
}
}
}
return false;
}
});
}
}
here is Adapter class
package com.focusmedica.maadiabetes;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by windev on 8/2/2016.
*/
public class MainAdapter extends BaseAdapter implements Filterable {
ArrayList<DataModel> dataSet;
Context context;
DataModel content;
public ArrayList<DataModel> orig;
public MainAdapter(Context context, ArrayList dataSet) {
super();
this.context = context;
this.dataSet = dataSet;
}
#Override
public int getCount() {
return dataSet.size();
}
#Override
public Object getItem(int position) {
return dataSet.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
class ViewHolder {
private TextView tvChapterName;
private ImageView ivChapterIcon;
}
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
final ViewHolder viewHolder;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.card_layout, null);
viewHolder = new ViewHolder();
viewHolder.tvChapterName = (TextView) view.findViewById(R.id.tvChapterName);
viewHolder.ivChapterIcon=(ImageView)view.findViewById(R.id.ivChapterIcon);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
content = dataSet.get(position);
viewHolder.tvChapterName.setText(content.getChapterName());
viewHolder.ivChapterIcon.setImageResource(R.drawable.caticon);
return view;
}
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
final FilterResults oReturn = new FilterResults();
final ArrayList<DataModel> results = new ArrayList<>();
final ArrayList<DataModel> ids = new ArrayList<>();
if (orig == null)
orig = dataSet;
if (constraint != null) {
if (orig != null && orig.size() > 0) {
for (final DataModel g : orig) {
if (g.getChapterName().toLowerCase().contains(constraint.toString())||
g.getChapterName().toUpperCase().contains(constraint.toString()))
results.add(g);
}
}
oReturn.values = results;
}
return oReturn;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
dataSet = (ArrayList<DataModel>) results.values;
notifyDataSetChanged();
}
};
}
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
}
To get the "old" position (which is equivalent to the item ID) for an item in the filtered list:
#Override
public long getItemId(int position) {
int itemID;
// orig will be null only if we haven't filtered yet:
if (orig == null)
{
itemID = position;
}
else
{
itemID = orig.indexOf(dataSet.get(position));
}
return itemID;
}
Now use this method with the OnItemClickListener:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(MainActivity.this, SubActivity.class);
intent.putExtra("position", adapter.getItemId(position) );
startActivity(intent);
}
Note: if you ever need to use notifyDatasetChanged() it might be a good idea to override this method as well:
#Override
public void notifyDatasetChanged()
{
// either this or: orig = dataSet;
orig = null;
super.notifyDatasetChanged();
}
After filtering the 'ArrayList' will add data from the 0th position. So you will get position as 0,1,2. You have to use id instead of position.
Store data which you want to get, in an array and retrieve data select by user using position from the same array in onClick method of listview.

Get text content in EditText ListView after click button issue

I have a Listview of EditText and I need to get the String values of each edited row when I click a confirm button, but I don't know how.
I have tried to adapt some sample with no success ( I get always the default values and not the edited values).
My attempt is this
public class MyActivity extends Activity {
static int nItems;
ImageButton confirmButton;
ListView myList;
ListViewAdapterEditText adapterG1, adapterG2, adapterG3;
#Override
public void onCreate(Bundle savedInstanceState) {
.....
myList = (ListView) findViewById(R.id.listaG1);
myList.setItemsCanFocus(true);
adapterG1 = new ListViewAdapterEditText();
myList.setAdapter(adapterG1);
}
OnClickListener mConfirmButtonListener = new OnClickListener() {
public void onClick(View v) {
ArrayList a1 = adapterG1.getItems();
for (int i = 0; i < nItems; i++) {
System.out.println(a1.get(i)
+ "\n\n");
}
};
public class ListViewAdapterEditText extends BaseAdapter {
private LayoutInflater mInflater;
public ArrayList myItems = new ArrayList();
ListItem listItem;
public ListViewAdapterEditText() {
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for (int i = 0; i < nItems; i++) {
listItem = new ListItem();
listItem.caption = "Caption" + i;
myItems.add(listItem);
}
notifyDataSetChanged();
}
public int getCount() {
return myItems.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public ArrayList<String> getItems() {
ArrayList<String> items = new ArrayList<String>();
for (int i = 0; i < nItems; i++) {
ListItem li = (ListItem) myItems.get(i);
items.add(li.getCaption());
}
return items;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_item_row,
null);
holder.caption = (EditText) convertView
.findViewById(R.id.ItemCaption);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Fill EditText with the value you have in data source
holder.caption.setText(((ListItem) myItems.get(position)).caption);
// holder.caption.setText(myItems.get(position).caption);
holder.caption.setId(position);
// we need to update adapter once we finish with editing
holder.caption
.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
final int position = v.getId();
final EditText Caption = (EditText) v;
((ListItem) myItems.get(position)).caption = Caption
.getText().toString();
}
}
});
return convertView;
}
class ViewHolder {
EditText caption;
}
class ListItem {
String caption;
public String getCaption() {
return caption;
}
}
}
}
Could someone help me to solve this problem?
Are you sure your OnFocusChangeListener is called? If you edit the text in EditText then tap the confirm button, this listener will not be called in touch mode since the focus is still on the EditText.
Update: Consider the situation you edited the text in a EditText while didn't confirm and scrolled the ListView so that the item view is recycled, I'm not sure what is your preferred way, but if you want store the edited data, you can use setRecyclerListener(android.widget.AbsListView.RecyclerListener) to get notified when a item view is recycled so you can saved the edit result. To save the result of EditText showing on screen, you use methods like getChildAt to get item views visible on screen then get the EditText's text.
Update2: Another better and clean way is use TextWatcher and addTextChangeListener, this will notifies you when the text in EditText is changed.
Update3: I just write the following sample and test it, and it works on my phone. :)
Update4: I removed the previous code cause its performance is bad and creates a lot objects, you can check the following full sample instead:
Activity code :
package com.example.asynctasktest;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
/**
* #author Daniel Chow
*
* May 26, 2013 12:57:49 AM
*/
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.listview);
final TestAdapter adapter = new TestAdapter(this);
listView.setAdapter(adapter);
Button confirmButton = (Button) findViewById(R.id.confirm_button);
confirmButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
List<String> items = adapter.getItems();
for (int i = 0, n = items.size(); i < n; i++) {
Log.e("", items.get(i));
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Adapter code:
/**
*
*/
package com.example.asynctasktest;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
/**
* #author Daniel Chow
*
* May 26, 2013 1:13:02 AM */
public class TestAdapter extends BaseAdapter {
private List<String> items = new ArrayList<String>();
private Context context;
public TestAdapter(Context context) {
this.context = context;
for (int i = 0; i < 12; i++) {
items.add("caption " + i);
}
}
public List<String> getItems() {
return new ArrayList<String>(items);
}
#Override
public int getCount() {
return 12;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = new EditText(context);
holder = new ViewHolder();
holder.editText = (EditText) convertView;
holder.watcher = new EditTextWatcher();
holder.editText.addTextChangedListener(holder.watcher);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.watcher.setTarget(position);
holder.editText.setText(items.get(position));
return convertView;
}
private class EditTextWatcher implements TextWatcher {
private int target;
public void setTarget(int target) {
this.target = target;
}
#Override
public void afterTextChanged(Editable s) {
items.set(target, s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
}
private static class ViewHolder {
EditText editText;
EditTextWatcher watcher;
}
}
I usually follow a simpler technique
public class Item_Adapter extends BaseAdapter {
private String[] Val;
public Item_Adapter () {
Val= new String[nItems];
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
///bla bla
holder.caption
.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
final int position = v.getId();
final EditText Caption = (EditText) v;
((ListItem) myItems.get(position)).caption = Caption
.getText().toString();
Val[position]= Caption
.getText().toString();
}
}
});
///bla bla
return convertView;
}
/////most important returning your array so you can use it in the Activity
public String[] getVal() {
return Val;
}

How to add EditText in listview and get its value dynamically in all the rows?

I have Checkbox and EditText and a Textview in a listView. It gets value for the text view from a list. Checkbox will be checked dynamically. In the same way EditText also can be entered dynamically. Now my problem is, When i scroll the list view (up and down) after entering the text in the Edit text, I could not get the typed value. I check the check box also like that. But using the position, I set it correct. I Could not know How to set the EditText value to the list properly. Please help me. Here is my code:
main.xml: (Main xml for launch)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/my_list"
android:layout_width="fill_parent"
android:layout_height="250px" />
<Button
android:text="Save"
android:id="#+id/btnSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
row.xml: (ListView Row)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/label"
android:textSize="30sp"/>
<CheckBox
android:id="#+id/check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<EditText
android:text=""
android:id="#+id/txtAddress"
android:layout_width="150px"
android:layout_height="wrap_content"/>
</LinearLayout>
Model.Java: (It is the POJO class)
package com.checkboxlistview;
public class Model {
private String name;
private boolean selected;
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public void setName(String name) {
this.name = name;
}
public Model(String name) {
this.name = name;
}
public String getName() {
return name;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
MyAdapter.Java: (This is used to Hold the view in the list view using the converter and holder)
package com.checkboxlistview;
import java.util.List;
import android.app.Activity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
public class MyAdapter extends ArrayAdapter<Model> implements TextWatcher {
private final List<Model> list;
private final Activity context;
int listPosititon;
public MyAdapter(Activity context, List<Model> list) {
super(context, R.layout.row, list);
this.context = context;
this.list = list;
}
static class ViewHolder {
protected TextView text;
protected CheckBox checkbox;
protected EditText address;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
listPosititon = position;
ViewHolder viewHolder = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
convertView = inflator.inflate(R.layout.row, null);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) convertView
.findViewById(R.id.check);
viewHolder.address = (EditText) convertView
.findViewById(R.id.txtAddress);
viewHolder.checkbox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
int getPosition = (Integer) buttonView.getTag();
//Here we get the position that we have set for the checkbox using setTag.
list.get(getPosition).setSelected(
buttonView.isChecked());
// Set the value of checkbox to maintain its state.
}
});
viewHolder.address.addTextChangedListener(this);
convertView.setTag(viewHolder);
convertView.setTag(R.id.label, viewHolder.text);
convertView.setTag(R.id.check, viewHolder.checkbox);
convertView.setTag(R.id.txtAddress, viewHolder.address);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.checkbox.setTag(position); // This line is important.
viewHolder.text.setText(list.get(position).getName());
viewHolder.checkbox.setChecked(list.get(position).isSelected());
if (list.get(position).getAddress() != null) {
viewHolder.address.setText(list.get(position).getAddress() + "");
} else {
viewHolder.address.setText("");
}
return convertView;
}
#Override
public void afterTextChanged(Editable s) {
list.get(listPosititon).setAddress(s.toString());
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
}
MainActivity.java (This is the activity):
package com.checkboxlistview;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity {
ListView listView;
Button btnSave;
ArrayAdapter<Model> adapter;
List<Model> list = new ArrayList<Model>();
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
listView = (ListView) findViewById(R.id.my_list);
btnSave = (Button)findViewById(R.id.btnSave);
adapter = new MyAdapter(this,getModel());
listView.setAdapter(adapter);
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < list.size(); i++) {
Toast.makeText(getBaseContext(), "Name : "+list.get(i).getName() +" Selected: "+list.get(i).isSelected(), Toast.LENGTH_SHORT).show();
}
}
});
}
private List<Model> getModel() {
list.add(new Model("Linux"));
list.add(new Model("Windows7"));
list.add(new Model("Suse"));
list.add(new Model("Eclipse"));
list.add(new Model("Ubuntu"));
list.add(new Model("Solaris"));
list.add(new Model("Android"));
list.add(new Model("iPhone"));
list.add(new Model("Java"));
list.add(new Model(".Net"));
list.add(new Model("PHP"));
return list;
}
}
There is no error in the code. It runs well. I could maintain the checkbox position and display at the same position even I scroll up and down. But I could not get and set the EditText value properly. Please Help me out.
Thanks in advance.
you can achieve this using the custom list view.
find the example of listview with edittext is here
Easy and beautiful solution to handle EditText with listView:
(Does not require holder or RecycleView or anything else)
Brief explaination:
1) In getView method when you inflate the view, apply the myTextWatcher the editText. Pass this EditText to the myTextWatcher()
2) Inside getView Method find that EditText and set position as editText.setTag [Each time. not only when the view was inflated.]
3) Define MyTextWatcher. It should have reference to EditText on which it is applied.
4) myTextWatcher.onTextChanged() will read the tag set to the editText and do the required work
Modify your getView() method of Adapter class:
#Override
public View getView(int position, View convertView, final ViewGroup parent) {
if(convertView==null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.single_row_layout,parent,false);
EditText et = convertView.findViewById(R.id.idEditText);
et.addTextChangedListener(new MyTextWatcher(et));
}
//This is again required to find reference to EditText... so that 'position' can be applied on to it as 'tag' EACH time.
EditText editText = (EditText) convertView.findViewById(R.id.idEditText);;
//This tag will be used inside onTextChanged()
editText.setTag(position);
}
Define your MyTextWatcher class as:
private class MyTextWatcher implements TextWatcher{
//int position;
EditText et;
public MyTextWatcher(EditText editText){
this.et = editText;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(et.getTag()!=null){
// This is required to ensure EditText is edited by user and not through program
if(et.hasFocus()){
int position = (int)et.getTag();
String newText = et.getText()+"";
//Implement your actions here........
//you can get require things/ views from listView.getChildAt(position)..
}
}
}
#Override
public void afterTextChanged(Editable s) {
}
}
Just keep viewHolder.address.setTag(position) and it works perfect cheers.
Adapter Class:
package com.qzick.adapter;
import java.util.ArrayList;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.TextView;
import com.example.qzick.R;
import com.qzick.model.Get_All_Class_Model;
public class Get_Class_Adapter extends BaseAdapter {
protected ArrayList<Get_All_Class_Model> get_class_details;
LayoutInflater inflater;
Context context;
private int x = 1;
public Get_Class_Adapter(Context context,
ArrayList<Get_All_Class_Model> get_class_details) {
this.get_class_details = get_class_details;
this.inflater = LayoutInflater.from(context);
this.context = context;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return get_class_details.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return get_class_details.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = this.inflater.inflate(
R.layout.activity_adapter_class_ll, parent, false);
holder.textclass = (TextView) convertView
.findViewById(R.id.text_class_ll);
holder.txtid = (TextView) convertView.findViewById(R.id.text_id_ll);
holder.checkclass = (CheckBox) convertView
.findViewById(R.id.check_class_LL);
holder.edtsection = (EditText) convertView
.findViewById(R.id.edttxt_addsection_ll);
holder.checkclass
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
int getPosition = (Integer) buttonView.getTag();
get_class_details.get(getPosition).setChecked(
buttonView.isChecked());
notifyDataSetChanged();
}
});
convertView.setTag(holder);
convertView.setTag(R.id.check_class_LL, holder.checkclass);
convertView.setTag(R.id.edttxt_addsection_ll, holder.edtsection);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.checkclass.setTag(position);
holder.edtsection.setTag(position);
holder.edtsection.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
int pos = (Integer) holder.edtsection.getTag();
get_class_details.get(pos).setEdtsections(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
holder.txtid.setText(get_class_details.get(position).getId());
holder.textclass.setText(get_class_details.get(position).getText());
holder.edtsection.setText(get_class_details.get(position)
.getEdtsections());
holder.textclass.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
x++;
if (x % 2 == 0) {
holder.checkclass.setChecked(false);
} else {
holder.checkclass.setChecked(true);
}
}
});
holder.checkclass.setChecked(get_class_details.get(position)
.isChecked());
return convertView;
}
private class ViewHolder {
TextView textclass, txtid;`enter code here`
CheckBox checkclass;
EditText edtsection;
}
}

Android: ListView making a search Filter

Is there a way to create a search filter over my custom list view which created using BaseAdapter rather than ArrayAdapter, because I have only come across methods that are using ArrayAdapters in there Custom List Views. Follwing is what I have come acrossMaking a filter using Array Adapter
If you're using List collection then extend ArrayAdapter - it's subclass of BaseAdapter.
Override getView method (In your case just copy your old getView code with little modifications).
Override toString of object that is in your collection and set:
listView.setTextFilterEnabled(true);
Here is an example for list view created using base adapter.
I searched a lot but didn't get any satisfactorily solution.Hence I thought to put it up so that in future it might help others.
Here is the code of history_container.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<EditText android:layout_width="fill_parent" android:layout_height="wrap_content"
android:id="#+id/filter_text" />
<FrameLayout android:layout_width="fill_parent"
android:layout_height="fill_parent" android:id="#+id/historyContainerLayout" />
</LinearLayout>
Here is the code of history_list_view.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:gravity="left|center"
android:layout_width="wrap_content" android:paddingBottom="5px"
android:paddingTop="5px" android:paddingLeft="5px">
<TextView android:text="#+id/historytext" android:id="#+id/historytext"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="10px" android:textColor="#0099CC"/>
</LinearLayout>
Here is the code of history_schedule.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ScrollView android:id="#+id/scrollItemInfo"
android:layout_width="fill_parent" android:layout_height="1000dip">
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<ListView android:id="#+id/historylist" android:layout_height="1000dip"
android:layout_width="fill_parent"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
Sorry, I am not being able to put the code in correct format.Seems something has changed as there is no tag anymore which was nice.But for user convenience this is also a good idea to have tab.
Maybe it is my fault that I'm not being able to post in correct format.And seems like we cannot post xml file content..So, think how the layout would have designed.
The activity code is :-
package com.testfilter;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;
public class TestFilterListView extends Activity {
FrameLayout historyContainer;
ViewStub viewStub;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.history_container);
historyContainer = (FrameLayout) findViewById(R.id.historyContainerLayout);
EditText filterEditText = (EditText) findViewById(R.id.filter_text);
filterEditText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
historyContainer.removeAllViews();
final List<String> tempHistoryList = new ArrayList<String>();
tempHistoryList.addAll(historyList);
for(String data : historyList) {
if(data.indexOf((s.toString())) == -1) {
tempHistoryList.remove(data);
}
}
viewStub = new ViewStub(TestFilterListView.this, R.layout.history_schedule);
viewStub.setOnInflateListener(new ViewStub.OnInflateListener()
{
public void onInflate(ViewStub stub, View inflated)
{
setUIElements(inflated, tempHistoryList);
}
});
historyContainer.addView(viewStub);
viewStub.inflate();
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
setViewStub();
}
/********************************************************************************************************/
private void setViewStub()
{
historyList.add("first");
historyList.add("second");
historyList.add("third");
historyList.add("fourth");
historyList.add("fifth");
historyList.add("sixth");
historyList.add("seventh");
viewStub = new ViewStub(TestFilterListView.this, R.layout.history_schedule);
viewStub.setOnInflateListener(new ViewStub.OnInflateListener()
{
public void onInflate(ViewStub stub, View inflated)
{
setUIElements(inflated, historyList);
}
});
historyContainer.addView(viewStub);
viewStub.inflate();
}
/********************************************************************************************************/
final List<String> historyList = new ArrayList<String>();
String displayName = "";
ListView historyListView;
private void setUIElements(View v, List<String> historyLists)
{
if (v != null)
{
historyScheduleData.clear();
//historyList.clear();
historyScheduleData.addAll(historyLists);
historyListView = (ListView) findViewById(R.id.historylist);
historyListView.setAdapter(new BeatListAdapter(this));
registerForContextMenu(historyListView);
}
}
/********************************************************************************************************/
private static class BeatListAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public BeatListAdapter(Context context) {
mInflater = LayoutInflater.from(context);
}
public int getCount() {
return historyScheduleData.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.history_list_view, null);
holder = new ViewHolder();
holder.historyData = (TextView) convertView
.findViewById(R.id.historytext);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.historyData.setText(historyScheduleData.get(position));
return convertView;
}
static class ViewHolder {
TextView historyData;
}
}
private static final List<String> historyScheduleData = new ArrayList<String>();
}
ArrayAdapter is a child class of BaseAdapter.
Source code for ArrayAdapter is here. Take a look at it..
This should solve your problem.
Here is an example . Edit and use what you need.
public class CustomListAdapter extends BaseAdapter {
private ArrayList<String> countryStringList;
private ArrayList<Integer> countryImageList;
private LayoutInflater mInFlater;
// private Bitmap mIcon1;
// private Bitmap mIcon2;
private int layoutID;
private Context context;
// private LayoutInflater mInflater;
public CustomListAdapter(Context context, int textViewResourceId,
ArrayList<String> stringObjects, ArrayList<Integer> imgObjects) {
super();
this.context = context;
countryStringList = stringObjects;
countryImageList = imgObjects;
layoutID = textViewResourceId;
mInFlater = LayoutInflater.from(context);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
// return countryStringList.size();
return countryStringList.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
final ViewHolder holder;
if (convertView == null) {
convertView = mInFlater.inflate(layoutID, null);
holder = new ViewHolder();
holder.textCountryName = (TextView) convertView
.findViewById(R.id.txtSelectedCountryName);
holder.icon = (ImageView) convertView
.findViewById(R.id.imgSelectedCountryImage);
holder.textCountryPosition = (TextView) convertView
.findViewById(R.id.txtSelectedCountryPosition);
// holder.checkBoxListView=(CheckBox)convertView.findViewById(R.id.CheckBoxListView);
holder.relativeLayoutList = (RelativeLayout) convertView
.findViewById(R.id.relativeLayoutListItem);
holder.checkBoxListView = (CheckBox) convertView
.findViewById(R.id.checkBoxSelectedCountry);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
// holder=(ViewHolder)convertView.findViewById(R.id.TextViewIcon1)
}
holder.checkBoxListView.setTag(position);
holder.textCountryName.setText(countryStringList.get(position));
holder.textCountryPosition.setText(position + 1 + "/"
+ countryStringList.size());
holder.icon.setImageResource((countryImageList.get(position)));
if (ListViewController.checkStatusList.get(position).equalsIgnoreCase("present")) {
holder.checkBoxListView.setVisibility(View.VISIBLE);
} else {
holder.checkBoxListView.setVisibility(View.GONE);
}
/*
* holder.checkBoxListView.setOnCheckedChangeListener(new
* OnCheckedChangeListener(){
*
* #Override public void onCheckedChanged(CompoundButton buttonView,
* boolean isChecked) { // TODO Auto-generated method stub
*
* ListActivityImplementation listActivityImplementation = new
* ListActivityImplementation(); //show("Checkbox");
* ListActivityImplementation.countryStringList.remove(position);
* ListActivityImplementation.countryImageList.remove(position);
* ListActivityImplementation.lv.invalidateViews();
*
* //ListActivityImplementation.show("Checkbox"); }
*
* }) ;
*/
holder.textCountryName.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
holder.textCountryPosition.setText(position + 1 + "/"
+ countryStringList.size() + "clicked");
}
});
holder.checkBoxListView
.setOnCheckedChangeListener(new android.widget.CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
MathHelper.showToast(context, buttonView.getTag()
+ " clicked");
}
});
return convertView;
}
}
class ViewHolder {
TextView textCountryName;
ImageView icon;
TextView textCountryPosition;
RelativeLayout relativeLayoutList;
CheckBox checkBoxListView;
}

Categories

Resources