I implement custom listview containing a checked textview. My wish is to change the state of the checkbox on click, but it seems not to be simple, as I thought it would be. Additionally I would like to check the checkboxes of items, that are stored in database, how could it be done? At the moment I have an activity which shows the elements, handles the click on the checkbox (not the list item!), but canĀ“t change the checkbox status by items stored in database.
This is my custom list item:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp">
<CheckedTextView
android:id="#+id/name"
android:layout_width="409dp"
android:layout_height="30dp"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:paddingStart="5dp"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/type"
android:layout_width="409dp"
android:layout_height="34dp"
android:paddingStart="5dp"
android:textSize="18sp"
android:textStyle="italic"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/name" />
</androidx.constraintlayout.widget.ConstraintLayout>
This is my adapter:
public class CustomAdapter extends BaseAdapter
{
private List<CustomElement> elems;
private LayoutInflater inflater;
public HueBulbAdapter(Context ctx, List<CustomElement> elems)
{
this.elems = elems;
inflater = LayoutInflater.from(ctx);
}
#Override
public int getCount()
{
return elems.size();
}
#Override
public Object getItem(int position)
{
return null;
}
#Override
public long getItemId(int position)
{
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ConstraintLayout result = (ConstraintLayout) inflater.inflate(R.layout.custom_elems, parent, false);
CheckedTextView name = result.findViewById(R.id.name);
TextView type = result.findViewById(R.id.type);
CustomElement elem = elems.get(position);
name.setText(elem.getName());
type.setText(elem.getType());
result.setTag(position);
toggle(name);
return result;
}
private void toggle(CheckedTextView ctv) {
ctv.setOnClickListener(v -> {
ctv.setChecked(!ctv.isChecked());
});
}
}
And this is my activity:
[...]
elemsView.setOnItemClickListener((parent, view, position, id) ->
{
if (!selected.containsKey(elemList.get(position).getName()))
{
selected.put(elemList.get(position).getName(), elemList.get(position));
} else
{
selected.remove(elemList.get(position).getName());
}
});
[...]
Maybe I am using wrong components to reach my target? Any Ideas how to do it this way or in a better way?
Thanks for your help!
Few suggestions:
Add a boolean variable to the CustomElement model to track if item is checked or not checked.
Add private boolean isChecked; and generate getter and setter for it.
In adapter class, use public Object getItem(int position) to return item in list, and not null.
Change to return elems.get(position);
In adapter class, replace toggle(name) with:
name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
elem.setChecked(!elem.isChecked()); // toggle
name.setChecked(elem.isChecked());
}
});
In your activity class, to access the updated list, use this:
for (int i = 0; i < mAdapter.getCount(); i++) {
CustomElement element = (CustomElement) mAdapter.getItem(i);
if (element.isChecked()) {...} else {...}
}
Optional. Search and implement ViewHolder Pattern in adapter class to improve the loading speed of ListView items.
Related
i manage to do when i click the item in my listview , beside the column will show a tick over there, but now i have a problem in when i click on my item the tick will show but there is no function for my onitemclicklistener event. how to let this two function work in same time. sorry for my english, hope can understand
this is my setOnItemClickListener event
condimentlist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView condimentitem =(TextView)view.findViewById(R.id.condcb);
String citem= condimentitem.getText().toString();
ArrayList<String> data = new ArrayList<String>();
data.add(citem);
String array[] = data.toArray(new String[0]);
for (int j = 0; j < array.length; j++) {
remark.append(String.valueOf(array[j]));
}
------condimentitem.setOnClickListener(new View.OnClickListener()-------
{
#Override
public void onClick(View v)
{
int visibility = btntick.getVisibility();
if(visibility == View.VISIBLE)
{
btntick.setVisibility(View.GONE);
}
else
{
btntick.setVisibility(View.VISIBLE);
}
}
});
}
});
this is my baseadapter to contor the tick
public class condimentlist extends BaseAdapter {
LayoutInflater mInflater;
private ArrayList<Integer> positions = new ArrayList<Integer>();
public ArrayList<Integer> getPositions() {
return positions;
}
public condimentlist() {
mInflater = LayoutInflater.from(getActivity());
}
#Override
public int getCount() {
return CondimentList.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.condimentlistview_details, null);
}
condcb = (TextView) convertView.findViewById(R.id.condcb);
final TextView tremark = (TextView) convertView.findViewById(R.id.Tremark);
btntick = (ImageView) convertView.findViewById(R.id.iv_tick);
Condiment myObj = CondimentList.get(position);
condcb.setText("" + myObj.getCondimentName());
-----------convertView.performClick ();------------------
return convertView;
}
condimentlistview_details.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/condcb"
android:text="Press"
android:layout_width="150dp"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:textSize="18sp" />
<ImageButton
android:layout_width="15dp"
android:layout_height="15dp"
android:background="#drawable/tick"
android:id="#+id/iv_tick"
android:visibility="gone"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="150dp"
android:layout_marginStart="150dp" />
</RelativeLayout>
I think problem is ImageButton in your listview Row xml file.
Put android:focusable="false" , and see it works!!!
<ImageButton
android:layout_width="15dp"
android:layout_height="15dp"
android:background="#drawable/tick"
android:id="#+id/iv_tick"
android:visibility="gone"
android:focusable="false"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="150dp"
android:layout_marginStart="150dp" />
Below is one of the question i answered before, you may need to create a list with one of the element of boolean as a flag. When you select, you turn that flag into true. Hope it helps.
enter link description here
You could define a static ArrayList in your activity class, then retrieve everything from that array list in the base adapter with a Hashmap. Then, you could use SetOnItemClickListener in your activity class to get the correct value of each row by referencing the activity's array list's position.
Works for me flawlessly. Let me know if you need example code.
Write this code inside BASE ADAPTER's getView()
condimentitem.setOnClickListener(new View.OnClickListener()-------
{
#Override
public void onClick(View v)
{
int visibility = btntick.getVisibility();
if(visibility == View.VISIBLE)
{
btntick.setVisibility(View.GONE);
}
else
{
btntick.setVisibility(View.VISIBLE);
}
}
});
Add convertView.performClick() inside condcb.OnClick method in adapter.
I am beginner of Android programming and need little help.
I have an array of objects that should be shown in listview. Here is a code of class:
public class Car {
public String img;
public String thumbnail;
public String manufacturer;
public String model;
public int price;
public String description;
}
Thumbnail is a string variable that contains URL of thumbnail to be shown.
I also have array of a few Car objects called "cars" declared in my DataStorage class.
I want only 2 things of every object to be shown in my customized listview: thumbnail (from internet) and model.
I created layout item.xml, which should represent one item of listview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#android:color/holo_blue_dark">
<ImageView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:text="left"
android:id="#+id/image_tmb"
android:layout_gravity="left|center_vertical"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:background="#android:color/holo_blue_dark">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:paddingBottom="10dp"
android:id="#+id/name"
android:layout_weight="1"
android:textSize="23dp"/>
</LinearLayout>
</LinearLayout>
TextView should be filled with model and Imageview should be filled with thumbnail.
I also created class MyAdapter which should fill listview:
public class MyAdapter extends BaseAdapter {
private Context myContext;
public MyAdapter(Context context) {
this.myContext = context;
}
#Override
public int getCount() {
return DataStorage.cars.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
//Here I should customize my view but don't know how.
}
I created listview element in activity_main.xml and delcared it in MainActivity:
ListView lv=(ListView) findViewById(R.id.lv);
So, how would I do my task?
A simple pattern would look something like this
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
// Inflate the view if it doesn't already exist
if (view == null) {
LayoutInflater.from(getContext()).inflate(R.layout.item, parent, false);
}
// Get your current Car object
Car c = getItem(i);
// Initialize the views
ImageView image = (ImageView) view.findViewById(R.id.image_tmb);
TextView name = (TextView) view.findViewById(R.id.name);
// Fill the views according to the car's properties
/* NOTE: I'm not going to go in depth to explain how to set
an ImageView image from a URL, as it is an entirely different question,
so I'll put a link to this library below */
Picasso.with(myContext).load(c.thumbnail).into(image);
name.setText(c.model);
}
You'll need to modify getItem to actually get the item, instead of returning null..
#Override
public Object getItem(int position) {
return DataStorage.cars[position];
}
Then, set up your adapter in your Activity/Fragment/Whatever, like this
MyAdapter mAdapter = new MyAdapter(this);
lv.setAdapter(mAdapter);
If you're going to be doing a lot with images and don't want to write your own implementation, Picasso is a really easy library to use.
I'm new in android..
I would like to create the different views in Listview using Custom Adapter.
Please suggest me how I can do this.
In first row there will be a single Item and in second row there will be two item and so on..
Please Check the attached screen..
Thanks in advance
Define a custom layout of how you want the list row like this
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="#dimen/headerHeightCustRow"
android:background="#FFFFFF"
tools:ignore="HardcodedText" >
<TextView
android:id="#+id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dip"
android:layout_marginLeft="#dimen/viewSpace1"
android:text="Varun Mad"
android:textSize="#dimen/logout_textSize"
android:textStyle="bold"
android:textColor="#color/orange_normal" />
<TextView
android:id="#+id/txtCustId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginLeft="#dimen/viewSpace3"
android:layout_marginTop="#dimen/viewSpace3"
android:layout_marginRight="#dimen/viewSpace3"
android:text="10549"
android:layout_centerVertical="true"
android:textColor="#color/orange_normal"
android:textSize="15sp" />
<TextView
android:id="#+id/txtPhone"
android:layout_below="#id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/viewSpace1"
android:text="(886)677-8855"
android:textColor="#color/orange_normal"
android:textSize="#dimen/vsText" />
<TextView
android:id="#+id/txtEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/viewSpace1"
android:text="ggg#gmail.com"
android:textSize="#dimen/vsText"
android:layout_below="#id/txtPhone"
android:textColor="#color/orange_normal" />
<View
android:layout_width="fill_parent"
android:layout_height="0.5dip"
android:layout_alignParentBottom="true"
android:background="#color/greyDark" />
here is the adapter class
public class SearchCustomerAdapter extends BaseAdapter {
Context ctx;
LayoutInflater lInflater;
ArrayList<SearchCustomerItem> objects;
public SearchCustomerAdapter(Context context, ArrayList<SearchCustomerItem> products) {
ctx = context;
objects = products;
lInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return objects.size();
}
#Override
public Object getItem(int position) {
return objects.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.search_cust_row, parent, false);
}
SearchCustomerItem p = getProduct(position);
((TextView) view.findViewById(R.id.txtName)).setText(p.customerName);
if (p.customerEmail.compareTo("anyType{}") == 0) {
((TextView) view.findViewById(R.id.txtEmail)).setText("");
} else {
((TextView) view.findViewById(R.id.txtEmail)).setText(p.customerEmail);
}
((TextView) view.findViewById(R.id.txtPhone)).setText(p.customerPhone);
((TextView) view.findViewById(R.id.txtCustId)).setText(p.customerId);
return view;
}
SearchCustomerItem getProduct(int position) {
return ((SearchCustomerItem) getItem(position));
}
#SuppressWarnings("unused")
ArrayList<SearchCustomerItem> getBox() {
ArrayList<SearchCustomerItem> box = new ArrayList<SearchCustomerItem>();
for (SearchCustomerItem p : objects) {
// if (p.box)
// box.add(p);
}
return box;
}
}
and the ITem Class
public class SearchCustomerItem {
public String customerName;
public String customerPhone;
public String customerEmail;
public String customerId;
public SearchCustomerItem(String _cName, String _cPhone, String _cEmail, String _cCustId) {
customerName = _cName;
customerPhone = _cPhone;
customerEmail = _cEmail;
customerId = _cCustId;
}
}
you can initialize the adapter,
add the items in Arraylist and show in the list by using
SearchCustomerAdapter boxAdapter;
ArrayList<SearchCustomerItem> products = new ArrayList<SearchCustomerItem>();
to add items in arraylist
products.add(new SearchCustomerItem("CustomerName","PhoneNo","Cust_EmailId","Cust_Id"));
//Add as many items you want
than
boxAdapter = new SearchCustomerAdapter(SearchActivity.this, products);
list.setAdapter(boxAdapter);
This link might help you. link
You should do it step by step.
Extend Base Adapter class by you Custom Adapter class
Override getView and other related methods
set the adapter to list view adapter.
Please note, this is really weird.
For some reason, the method setChoiceMode (ListView.CHOICE_MODE_SINGLE) no results.
I use it like this:
list = (ListView) findViewById(R.id.list);
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
list.setOnItemClickListener(OnItemClickListenerObject);
list.setAdapter(adapter);
The fact is that after I put the method setChoiceMode (), nothing has changed, RadioButtons not appeared.
I'm using a custom adapter and I have no problems with it? But I do not understand why Radiobuttons not shown.
Any ideas? (If you need additional code, ask and I'll post it.)
My adapter code:
public class ContactAdapter extends BaseAdapter {
private LayoutInflater inflater;
private ArrayList<Contact> contacts;
private View view;
public ContactAdapter(Context context, ArrayList<Contact> contacts) {
this.contacts = contacts;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return contacts.size();
}
#Override
public Object getItem(int position) {
return contacts.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
private Contact getContact(int position) {
return (Contact) getItem(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
view = convertView;
if (view == null) {
view = inflater.inflate(R.layout.contact_item, parent, false);
}
Contact c = getContact(position);
((TextView) view.findViewById(R.id.lv_name)).setText(c.getName() + " " + c.getSurname());
((ImageView) view.findViewById(R.id.lv_img)).setImageBitmap(c.getPhoto());
return view;
}
}
Below shows the layout that I use for ListView item.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_margin="8dp">
<ImageView
android:id="#+id/lv_img"
android:layout_width="75dp"
android:layout_height="75dp"
android:src="#drawable/default_user"
android:layout_weight="0"/>
<TextView
android:id="#+id/lv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="16dp"
android:layout_gravity="center_vertical"
android:textSize="24sp"/>
</LinearLayout>
Setting the choice mode does not automatically make radio buttons appear. All it does is add behavior which toggles a ListView row's Checkable or activation state. It's still up to the row's View to decide how to react to that. You'll need to create your own layout to inflate for a row that supports the activation state or the Checkable interface.
Android does provide some simple pre-made views that you can use. Here's just a couple you can choose from:
android.R.layout.simple_list_item_activated_1.xml
android.R.layout.simple_list_item_checked.xml
I have made an BaseAdapter that does not show the onclick effect on the rows when the items get selected (orange background).
Im wondering what is needed to make the OnClickedItem effect appear. I tried to set the OnItemClickListener on the list, but it did not help.
here is my code:
private class MyAdapter extends BaseAdapter{
private Bingo activity;
public MyAdapter(Bingo context){
this.activity = context;
items = new ArrayList<String>();
}
public void add(String item){
items.add(item);
notifyDataSetChanged();
}
public void clear(){
items.clear();
notifyDataSetChanged();
}
private ArrayList<String> items;
public int getCount() {
return items.size();
}
public Object getItem(int position) {
return items.get(position);
}
public long getItemId(int position) {
return position;
}
public boolean isEnabled(int position){
return true;
}
public View getView(int position, View convertView, ViewGroup parent) {
if(position == getCount() - 5 && getCount() < 100){
Log.d("dbg","Autoadding...");
activity.add();
}
View view = null;
if (convertView == null) {
Log.i("dbg","new:"+position);
view = View.inflate(activity, R.layout.item, null);
}
else {
Log.i("dbg","recycle:"+position);
view = convertView;
}
TextView text = (TextView)view.findViewById(R.id.text);
text.setText(items.get(position)+" -------> pos:"+position);
return view;
}
}
item.xml that is inflated...
LinearLayout
android:id="#+id/root"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:layout_marginRight="10dp"
android:src="#drawable/icon"
LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFF"
android:singleLine="true"
Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK"
android:layout_gravity="right"
android:gravity="center_horizontal"
android:inputType="textUri"
/LinearLayout
/LinearLayout
Try this
For ListView,
final ListView list = (ListView) findViewById(R.id.list);
list.setItemsCanFocus(false);
Also, make sure that for Button inside list item set focusable false
android:focusable="false"
android:focusableInTouchMode="false"
Similar Question
Ohh, i think i found the problem... its the button ... if i remove the button from the inflated view the row can be selected.... if the button is there i can only click/focus on the button...