So I have a simple Custom ListView. When a button in the ListView is clicked, a Toast is supposed to be created (as a test, will later switch to an activity depending on the pressed category).
The problem is, that nothing happens when any of the buttons are clicked.
Not sure how to fix it at the moment.
Category Table
public class CategoryTable extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.category_table);
populateTable();
}
private void populateTable() {
final ListView mListView = findViewById(R.id.listView);
Category One = new Category(" One");
Category Two = new Category(" Two");
Category Three = new Category(" Three");
Category Four = new Category(" Four");
final ArrayList<Category> categoryList = new ArrayList<>();
categoryList.add(One);
categoryList.add(Two);
categoryList.add(Three);
categoryList.add(Four);
CategoryListAdapter adapter = new CategoryListAdapter(this, R.layout.adapter_view_layout, categoryList);
mListView.setAdapter(adapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast toast = Toast.makeText(getApplicationContext(), "Clicked", Toast.LENGTH_SHORT);
toast.show();
}
}
});
}
Custom Adapter
public class CategoryListAdapter extends ArrayAdapter<Category> {
private Context mContext;
int mResource;
public CategoryListAdapter(Context context, int resource, ArrayList<Category> objects) {
super(context, resource, objects);
mContext = context;
mResource = resource;
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String name = getItem(position).getName();
Category category = new Category(name);
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
Button catName = convertView.findViewById(R.id.btnNextTbl);
catName.setText(name);
return convertView;
}
}
I've also added
android:descendantFocusability="blocksDescendants"
to the custom adapter xml file (didn't seem to change anything though).
Will include more code if needed.
Any help would be greatly appreciated.
its because you have the listener for when you click the actual row, not the button inside the row. if you want it on button click you will need to do something like this
public class CategoryListAdapter extends ArrayAdapter<Category> {
private Context mContext;
int mResource;
public CategoryListAdapter(Context context, int resource, ArrayList<Category> objects) {
super(context, resource, objects);
mContext = context;
mResource = resource;
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String name = getItem(position).getName();
Category category = new Category(name);
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
Button catName = convertView.findViewById(R.id.btnNextTbl);
catName.setText(name);
catName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//make call back to activity to do whatever you want
}
});
return convertView;
}
}
Related
I'm creating an item order list for a restaurrant.
The goal is to set onClickListener to each button(+/-) in each row in the list so it can count how many items are ordered.
Can anyone please help me with this code? i have managed to set a listener but it does not count the items properly when clicking among the rows.
public class MainActivity extends ListActivity {
private String[] item_names = {"Mozza Cheese", "Chicken Rings", "Onion Rings", "Calamari Rings"};
private int item_counter = 1;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.view_order_list);
listAdapter();
}
private void listAdapter(){
setListAdapter(new MyAdapter(this,
android.R.layout.simple_list_item_2, R.id.items_name_order, item_names));
}
private class MyAdapter extends ArrayAdapter<String> {
public MyAdapter(Context context, int resource, int textViewResourceId, String[] strings) {
super(context, resource, textViewResourceId, strings);
}
#SuppressLint("ViewHolder")
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.view_order, parent, false);
TextView item_name = (TextView) convertView.findViewById(R.id.items_name_order);
final TextView item_count = (TextView) convertView.findViewById(R.id.count_item_order);
Button plus = (Button) convertView.findViewById(R.id.button_plus_order);
Button minus = (Button) convertView.findViewById(R.id.button_minus_order);
item_name.setText(item_names[position]);
plus.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
item_counter++;
item_count.setText(Integer.toString(item_counter));
}
});
return convertView;
}
}
}
note new int array item_counter, rest as in my comment to question
public class MainActivity extends ListActivity {
private String[] item_names = {"Mozza Cheese", "Chicken Rings", "Onion Rings", "Calamari Rings"};
private int[] item_counter = {0, 0, 0, 0};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.view_order_list);
listAdapter();
}
private void listAdapter(){
setListAdapter(new MyAdapter(this,
android.R.layout.simple_list_item_2, R.id.items_name_order, item_names));
}
private class MyAdapter extends ArrayAdapter<String> {
public MyAdapter(Context context, int resource, int textViewResourceId, String[] strings) {
super(context, resource, textViewResourceId, strings);
}
#SuppressLint("ViewHolder")
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.view_order, parent, false);
TextView item_name = (TextView) convertView.findViewById(R.id.items_name_order);
final TextView item_count = (TextView) convertView.findViewById(R.id.count_item_order);
Button plus = (Button) convertView.findViewById(R.id.button_plus_order);
Button minus = (Button) convertView.findViewById(R.id.button_minus_order);
item_name.setText(item_names[position]);
item_count.setText(item_counter[position];
plus.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
item_counter[position]++;
notifyDataSetChanged();
}
});
return convertView;
}
}
}
I have a custom listview: http://i.stack.imgur.com/oBCCG.png
Up on clicking an item of 'ListView' the 'ImageView' with that "mark" becomes visible.
But the problem is that I need only ONE item to be marked. How can I deselect all others items up on click?
CustomList adapter:
private class TimeZoneItemAdapter extends ArrayAdapter<String> {
private Activity myContext;
private ArrayList<String> datas;
public TimeZoneItemAdapter(Context context, int textViewResourceId, ArrayList<String> objects) {
super(context, textViewResourceId, objects);
myContext = (Activity) context;
datas = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = myContext.getLayoutInflater();
convertView = inflater.inflate(R.layout.listview_item, null);
viewHolder = new ViewHolder();
viewHolder.postNameView = (TextView) convertView.findViewById(R.id.listview_item);
viewHolder.postImageView = (ImageView) convertView.findViewById(R.id.image_mark);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.postNameView.setText(datas.get(position));
viewHolder.postNameView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//How to deselect all other items here?
if (viewHolder.postImageView.getVisibility() != View.VISIBLE) {
viewHolder.postImageView.setVisibility(View.VISIBLE);
} else {
viewHolder.postImageView.setVisibility(View.INVISIBLE);
}
}
});
return convertView;
}
class ViewHolder {
TextView postNameView;
ImageView postImageView;
}
}
setting the adapter:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_time_zone, container, false);
// Set the adapter
mListView = (ListView) view.findViewById(R.id.listView_timezones);
imageCheck = (ImageView) view.findViewById(R.id.image_mark);
mListView.setAdapter(new TimeZoneItemAdapter(
getActivity(),
R.layout.listview_item,
dataTimezones.getZonesList()
));
return view;
}
Thanks for any help!
You might want to keep track of the currently selected list view item position in a dedicated integer variable. Then you would only need to call notifyDataSetChanged() on the adapter each time an item is selected and set the ImageView as visible in getView() if yourSelectedPosition == position.
Also check out the setOnItemClickListener() method on ListView.
EDIT:
Here's some code.
First in the Activity attach a listener to the ListView:
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick (AdapterView<?> parent, View view, int position, long id) {
timeZoneItemAdapter.selectedPosition = position;
timeZoneItemAdapter.notifyDataSetChanged();
}
});
and the adapter should look something like this:
private class TimeZoneItemAdapter extends ArrayAdapter<String> {
private Activity myContext;
private ArrayList<String> datas;
public int selectedPosition = -1;
public TimeZoneItemAdapter(Context context, int textViewResourceId, ArrayList<String> objects) {
super(context, textViewResourceId, objects);
myContext = (Activity) context;
datas = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = myContext.getLayoutInflater().inflate(R.layout.listview_item, null);
TextView postNameView = (TextView) convertView.findViewById(R.id.listview_item);
ImageView imageMark = (ImageView) convertView.findViewById(R.id.image_mark);
postNameView.setText(datas.get(position));
imageMark.setVisibility(selectedPosition == position ? View.VISIBLE : View.GONE);
return convertView;
}
}
This solution gets rid of the ViewHolder, but would it work for you?
I'm trying to use an adapter in my android application to add images in my items in my listView :
this is my adapter :
public class ItemAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] Names;
private final int rowResourceId;
public ItemAdapter(Context context, int textViewResourceId, String[] objects) {
super(context, textViewResourceId, objects);
this.context = context;
this.Names = objects;
this.rowResourceId = textViewResourceId;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(rowResourceId, parent, false);
ImageView imageView = (ImageView) rowView.findViewById(R.id.imageFileView);
TextView textView = (TextView) rowView.findViewById(R.id.fileName);
String name = Names[position];
String extFile = Names[position].substring(Names[position].lastIndexOf("."));
textView.setText(name);
String uri = "drawable/"+extFile;
// int imageResource = R.drawable.icon;
//int imageResource = getResources().getIdentifier(uri, null, getPackageName());
// set image to ImageView
Uri imgUri=Uri.parse(uri);
imageView.setImageURI(imgUri);
return rowView;
}
}
I use also also another adapter in my application to add the pull to refresh to my listView but this one works perfectly.
i thing that it does not call my "ItemAdapter" cause the system.out.print doesn't show anything
I call my adapter like this :
public void getList(){
client.get(server+"get/files/1"+folderPath, new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONArray files) {
String[] listeNames=new String[files.length()];
for (int i = 0; i < files.length(); i++) {
try {
listeNames[i]=files.getString(i);
} catch (JSONException e) {
System.err.println("error :"+e.getMessage());
}
}
list_files.setAdapter(new ItemAdapter(mainActivity,android.R.layout.simple_list_item_1,listeNames));
list_files.setAdapter(new ArrayAdapter<String>(mainActivity,android.R.layout.simple_list_item_1,listeNames));
((PullToRefreshListView) list_files).onRefreshComplete();
}
});
}
A ListView can have only one Adapter. The problem is that you are doing this:
list_files.setAdapter(new ItemAdapter(mainActivity,android.R.layout.simple_list_item_1,listeNames));
list_files.setAdapter(new ArrayAdapter<String>(mainActivity,android.R.layout.simple_list_item_1,listeNames));
So the second Adapter overrides the first one. This is the reason why this one works perfectly and why the ItemAdapter is never called.
You should try to gather these two Adapters into a single one.
I am trying to make an Activity that basically holds a list on song items that are "semi-complex." The output of one list item can be found here. I found what seemed like a good example online to follow to create such a thing, and that could is below.
However, ArrayAdapters apparently can only be used on SIMPLE TextViews (this is basically the error I am getting from the LogCat), and I have 3 TextViews I have to control and the color in one of them along with an image. So the code will not compile. I have looked into ListAdapters, but the underlining structure is completely different from the ArrayAdapter is is far from a 1 to 1 translation to it.
What should I do, and use? I am lost right now!
FYI, in the LogCat I get the following (NOTE I removed the LogCat code from the code below...that was put in right AFTER the super call in the constructor of SimpleSongAdapter)...
Here is my SimpleSongAdapter class
public class SimpleSongAdapter extends ArrayAdapter<SimpleSong> {
Context context;
int layoutResourceID;
SimpleSong song[] = null;
public SimpleSongAdapter(Context context, int resource, SimpleSong[] data) {
super(context, resource, data);
this.layoutResourceID = resource;
this.context = context;
this.song = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
super.getView(position, convertView, parent);
View row = convertView;
SimpleSongHolder songHolder = null;
if (row == null) {
LayoutInflater newView = ((Activity) context).getLayoutInflater();
row = newView.inflate(this.layoutResourceID, parent, false);
ExtractLayoutResources(parent, row, songHolder);
row.setTag(songHolder);
} else {
songHolder = (SimpleSongHolder) row.getTag();
}
SetLayoutResource(songHolder, position);
return row;
}
private void SetLayoutResource(SimpleSongHolder songHolder, int position) {
SimpleSong currentSong = song[position];
songHolder.imgSongThumbnail.setImageResource(currentSong.thumbnail);
songHolder.txtSongName.setText(currentSong.songName);
songHolder.txtGroupName.setText(currentSong.groupName);
String metaText = "";
int colorID = 0;
// switch statement to set metaText and colorID
songHolder.txtSongMetaInfo.setText(metaText);
songHolder.txtSongMetaInfo.setTextColor(colorID);
}
private void ExtractLayoutResources(ViewGroup parent, View row, SimpleSongHolder songHolder) {
songHolder = new SimpleSongHolder();
songHolder.imgSongThumbnail = (ImageView) row.findViewById(R.id.imgSongThumbnail);
songHolder.txtSongName = (TextView) row.findViewById(R.id.txtSongName);
songHolder.txtGroupName = (TextView) row.findViewById(R.id.txtGroupName);
songHolder.txtSongMetaInfo = (TextView) row.findViewById(R.id.txtSongMetaInfo);
}
private static class SimpleSongHolder {
ImageView imgSongThumbnail;
TextView txtSongName;
TextView txtGroupName;
TextView txtSongMetaInfo;
}
}
In SimpleSong class I have
public class SimpleSong {
public int thumbnail;
public String songName;
public String groupName;
public String songMetaInfo;
public RemixType remixType;
public SimpleSong(String songName, String groupName) {
this.songName = songName;
this.groupName = groupName;
}
// Sets to set other attributes
In MainActivity I have
public class MainActivity extends Activity {
private ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SimpleSong songs[] = new SimpleSong[] {
// new SimpleSong mock object list
};
listView = (ListView) findViewById(R.id.songView);
View listHeader = (View) getLayoutInflater().inflate(R.layout.list_header, null);
SimpleSongAdapter songAdapter = new SimpleSongAdapter(this, R.layout.list_item, songs);
listView.addHeaderView(listHeader);
listView.setAdapter(songAdapter);
}
You are invoking this constructor:
public ArrayAdapter (Context context, int resource, T[] objects)
Which expects the resource id to be the id of a TextView, but you are passing the id of the layout.
You need to use the following constructor in stead:
public ArrayAdapter (Context context, int resource, int textViewResourceId, T[] objects)
And call it like:
SimpleSongAdapter songAdapter = new SimpleSongAdapter(this, R.layout.list_item, 0, songs);
I have used ListView with custom adapter, so my ListView includes CheckBox, but problem is that when I scroll down, checked CheckBoxes uncheck, how can I do it with this code?
UPDATE
My custom adapter:
public class AppsArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private List<Integer> checkedItems;
private final String DefaultApps = "def_apps";
public AppsArrayAdapter(Context context, String[] values, List<Integer> checkedItems) {//XXX
super(context, R.layout.apps, values);
this.context = context;
this.checkedItems = checkedItems;//XXX
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
SharedPreferences myPrefsApps =context.getSharedPreferences("myPrefsApps", Context.MODE_PRIVATE);
String prefNameDefaultApps = myPrefsApps.getString(DefaultApps, "");
String prefNameDefaultAppsVer = myPrefsApps.getString(DefaultAppsVer, "");
LayoutInflater inflater = (LayoutInflater)context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.apps, parent, false);
TextView text_apps = (TextView)rowView.findViewById(R.id.text_apps);
CheckBox check = (CheckBox)rowView.findViewById(R.id.check_apps);
text_apps.setText(prefNameDefaultApps.split("\n")[position]);
check.setChecked(checkedItems.contains((Integer) position));
return rowView;
}
}
And my Activity:
public class AppsActivity extends ListActivity {
private final String DefaultApps = "def_apps";
private List<Integer> checkedItems = new ArrayList<Integer>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppsArrayAdapter adapter = new AppsArrayAdapter(this, prefNameDefaultApps.split("\n"), checkedItems);
setListAdapter(adapter);
}
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
if(checkedItems.contains((Integer) position)) checkedItems.remove((Integer) position);
else checkedItems.add((Integer) position);
}
// initialise the list
private List<Integer> selection = new ArrayList<Integer>();
for (String str: prefNameDefaultApps.split("\n")) {
selection.add(0);
}
// setting the list
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
if(CheckBox is checked) {//(check if the checkbox is checked )
selection.set(position, 1);
}
else{
selection.set(position, 0);
}
}
// show in the listView
#Override
public View getView(int position, View convertView, ViewGroup parent) {
....
....
check.setChecked(selection.get(position) == 0 ? false : true);
}
This should get you going :)
I'm not entirely sure whether there is a standard solution in Android, but this should do the trick:
public class AppsArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private List<Integer> checkedItems;//Here we save the position of the selected items.
private final String DefaultApps = "def_apps";
//This will be invoked when one of the CheckBoxes gets clicked. It will update the checkedItems list.
private View.OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Integer position = (Integer) v.getTag();
if(checkedItems.contains(position)) checkedItems.remove(position);
else checkedItems.add(position);
}
};
public AppsArrayAdapter(Context context, String[] values, List<Integer> checkedItems) {//XXX
super(context, R.layout.apps, values);
this.context = context;
this.checkedItems = checkedItems;//XXX
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
SharedPreferences myPrefsApps =context.getSharedPreferences("myPrefsApps", Context.MODE_PRIVATE);
String prefNameDefaultApps = myPrefsApps.getString(DefaultApps, "");
//You shouldn't inflate the View everytime getView() is called,
/*LayoutInflater inflater = (LayoutInflater)context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.apps, parent, false);*/
//rather let the superclass handle it as it's more efficient.
View rowView = super.getView(position, convertView, parent);
TextView text_apps = (TextView)rowView.findViewById(R.id.text_apps);
CheckBox check = (CheckBox)rowView.findViewById(R.id.check_apps);
text_apps.setText(prefNameDefaultApps.split("\n")[position]);
check.setChecked(checkedItems.contains((Integer) position));//XXX
check.setTag((Integer) position);//XXX
check.setOnClickListener(onClickListener);//XXX
return rowView;
}
}
In your ListActivity, add a field private List<Integer> checkedItems = new ArrayList<Integer>;. You have to pass this List in the Adapter constructor!
If you want to check whether the nth item in your ListView was selected, just look whether n is saved in checkedItems, i.e.
if(checkedItems.contains(requestedItemPosition)) {
//Item was selected.
} else {
//Item was not selected.
}
I really recommend you not to inflate the views by yourself.
Try this: (your custom adapter)
public class AppsArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private List<Integer> checkedItems;
private final String DefaultApps = "def_apps";
LayoutInflater inflater;
public AppsArrayAdapter(Context context, String[] values, List<Integer> checkedItems) {//XXX
super(context, R.layout.apps, values);
this.context = context;
this.checkedItems = checkedItems;//XXX
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
SharedPreferences myPrefsApps =context.getSharedPreferences("myPrefsApps", Context.MODE_PRIVATE);
String prefNameDefaultApps = myPrefsApps.getString(DefaultApps, "");
String prefNameDefaultAppsVer = myPrefsApps.getString(DefaultAppsVer, "");
View rowView = convertView;
ViewHolder viewH = new ViewHolder();
if ( rowView == null){
rowView = inflater.inflate(R.layout.apps, parent, false);
viewH.text_apps = (TextView)rowView.findViewById(R.id.text_apps);
viewH.check = (CheckBox)rowView.findViewById(R.id.check_apps);
rowView.setTag(viewH);
}else{
viewH = (ViewHolder) rowView.getTag();
}
viewH.text_apps.setText(prefNameDefaultApps.split("\n")[position]);
viewH.check.setChecked(checkedItems.contains((Integer) position));
return rowView;
}
static class ViewHolder {
public TextView text_apps;
public CheckBox check;
}
}
Hope this helps :)
you should use
MyAdapter newad=(MyAdapter)adapter.getAdapter();
newad.notifyDataSetChanged();
this code in onitem click method
and MyAdapter is class of Adapter and make new object like this one
and in adapter class you should have to write a line
LayoutInflater in;
in=(LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
in adapter constructor simple