Custom Adapter for List View
public class ListAdapter extends ArrayAdapter<Item> {
private int resourceLayout;
private Context mContext;
public ListAdapter(Context context, int resource, List<Item> items) {
super(context, resource, items);
this.resourceLayout = resource;
this.mContext = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(mContext);
v = vi.inflate(resourceLayout, null);
}
Item p = getItem(position);
if (p != null) {
TextView tt1 = (TextView) v.findViewById(R.id.id);
TextView tt2 = (TextView) v.findViewById(R.id.categoryId);
TextView tt3 = (TextView) v.findViewById(R.id.description);
if (tt1 != null) {
tt1.setText(p.getId());
}
if (tt2 != null) {
tt2.setText(p.getCategory().getId());
}
if (tt3 != null) {
tt3.setText(p.getDescription());
}
}
return v;
}
}
This is a class I had used for my project. You need to have a collection of your items which you want to display, in my case it's <Item>
. You need to override View getView(int position, View convertView, ViewGroup parent)
method.
R.layout.itemlistrow
defines the row of the ListView
.
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:orientation="vertical"
android:layout_width="fill_parent">
<TableRow android:layout_width="fill_parent"
android:id="@+id/TableRow01"
android:layout_height="wrap_content">
<TextView android:textColor="#FFFFFF"
android:id="@+id/id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="id" android:textStyle="bold"
android:gravity="left"
android:layout_weight="1"
android:typeface="monospace"
android:height="40sp" />
</TableRow>
<TableRow android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TextView android:textColor="#FFFFFF"
android:id="@+id/categoryId"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="categoryId"
android:layout_weight="1"
android:height="20sp" />
<TextView android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:textColor="#FFFFFF"
android:gravity="right"
android:id="@+id/description"
android:text="description"
android:height="20sp" />
</TableRow>
</TableLayout>
In the MainActivity
define ListView
like this,
ListView yourListView = (ListView) findViewById(R.id.itemListView);
// get data from the table by the ListAdapter
ListAdapter customAdapter = new ListAdapter(this, R.layout.itemlistrow, List<yourItem>);
yourListView .setAdapter(customAdapter);
How to implement a custom adapter with listview?
You should just change your super constructor invoke. Because it receive the layout resource which you gonna inflate. Like this:
public IndustryAdapter(Context context, ArrayList<Industry> industries) {
super(context, android.R.layout.simple_list_item_1);
}
ListView & Custom Adapter dont work Kotlin
To the adapter, it's one item for one view. Your backing List has only one item. Your for loop inside getView()
is iterating some collection inside that single item, and setting the value of the same TextView over and over until it gets to the last one.
Since the backing type of your adapter is TestHero, your list view can only show one line item per instance of TestHero. You only have one instance of TestHero.
Based on what you're showing, you should make the backing type of your adapter whatever the type of the list TestHero.legends.all
is. In your coroutine, you can pull that list out of your TestHero and pass it to your Adapter. You'll need to make the backing list property mutable.
And like I said in the comments, don't use mutable lists for this. You should start with an empty list.
For example, if the type of this list is Legend, your adapter should look something like:
class HeroesAdapter(): BaseAdapter() {
var heroes: List<Legend> = emptyList()
override fun getCount(): Int = heroes.size
override fun getItem(position: Int): = heroes[position]
override fun getItemId(position: Int) = position
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: LayoutInflater.from(parent.context).inflate(R.layout.list_hero_view, parent, false)
val heroText: TextView = view.findViewById(R.id.textHeroView)
val hero = heroes[position]
heroText.text = hero.keys.first()
return view
}
}
And in your Activity, get rid of the listHero
property. In your coroutine, after you get your data, do
heroesAdapt.apply {
heroes = data.legends.all
notifyDataSetChanged()
}
Also, consider switching to RecyclerView. ListView is kind of obsolete and I keep expecting them to deprecate it because they have only worked on improving RecyclerView the past several years.
Setting Listener on individual item of custom adapter list view
If your item listener is not working then you can apply this on ListView in xml layout.
android:descendantFocusability="blocksDescendants"
You can put many clicks listeners if you need in adapter class like
public class MyAdapter extends ArrayAdapter<Contact> {
Context context;
public MyAdapter(Context context, ArrayList<Contact> users) {
super(context, 0, users);
this.context = context;
}
public View getView(int position, View convertView, ViewGroup parent) {
Contact user = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.listviewadapter, parent, false);
}
TextView name = convertView.findViewById(R.id.name);
TextView num = convertView.findViewById(R.id.num);
// Populate the data into the template view using the data object
name.setText(user.name);
num.setText(user.phone_number);
// can set click on name or num
name.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, position + "position clicked", Toast.LENGTH_SHORT).show();
}
});
// can set click on full list item
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, position + "position clicked", Toast.LENGTH_SHORT).show();
}
});
return convertView;
}
}
How to add items dynamically to a custom adapter for ListView
The problem is that your adapter's lfs
's field and your activity's elements
field both refer to the same List
instance. This happens because you pass elements
to the ListAdapter
constructor, and then simply assign this.lfs = lfs
.
So let's look at what happens when you pass elements
to updateItems()
...
public void updateItems(List<Lf> lfs) {
this.lfs.clear(); // this.lfs and the input lfs are the same list, so this clears both
this.lfs.addAll(lfs); // input lfs is now empty, so addAll() does nothing
this.notifyDataSetChanged();
}
Probably the best thing to do is to create a copy of the list in your adapter's constructor.
this.lfs = new ArrayList<>(lfs);
Now your adapter and activity will reference different lists, so this.lfs.clear()
won't accidentally clear out the very list you're passing to it.
List view with custom adapter don't show all items
In Custom_listview_adapter change
@Override
public int getCount(){
return this.spinner_array.length;
}
to
@Override
public int getCount(){
return this.data.size();
}
Search items from listview with custom adapter
You should implements Filterable in your Adapter
A custom ListView with a custom adapter in Android Studio
At first use ViewHolder
pattern. At second extend BaseAdapter
not AdapterView
. At third delete android:clickable="true"
from row.xml
. Clickable state must have ListView
in method onItemClickListener
, not own row.
Updated
For the Customized listview you can use BaseAdapter.
And With Adapter Class you it have some tips to make it smooth , for that you can refer this
Its also about resusability already created row's control instances.For that ViewHolder pattern i prefer to use to hold the objects. Please check this for more detail
Which is missing in your code of the adapter's getView Method.
For more explanation i leave comment in Adapter's getView Method.
Class to hold the details if you are gng to use thn naming convention should be proper
here first the name is "Object" which is wrong.
Activity
private ListView list;
private final ArrayList<RestaurantsDetails> pairs = new ArrayList<RestaurantsDetails>();
private Activity context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pairs.add(new RestaurantsDetails("McDonald's", "mcd"));
pairs.add(new RestaurantsDetails("Subway", "mcd"));
pairs.add(new RestaurantsDetails("Pizza Hut", "mcd"));
pairs.add(new RestaurantsDetails("Burger King", "mcd"));
list = (ListView) findViewById(R.id.listview);
AdapterViewCustom adapter = new AdapterViewCustom(this, pairs);
list.setAdapter(adapter);
list.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
@Override
public void onItemClick(android.widget.AdapterView<?> parent,
View view, int position, long id) {
Toast.makeText(getApplicationContext(),
pairs.get(position).name, Toast.LENGTH_LONG).show();
}
});
}
DataLayer Class
/**
* Use proper name For the class. Should not use the name like "Object" or
* the class which is already used by framework
*
*/
public class RestaurantsDetails {
public String name;
public String img;
public RestaurantsDetails(String name, String img) {
this.name = name;
this.img = img;
}
}
Adapter
public class AdapterViewCustom extends BaseAdapter {
private Activity context_1;
private ArrayList<RestaurantsDetails> pairs;
public AdapterViewCustom(Activity context,
ArrayList<RestaurantsDetails> pairs) {
context_1 = context;
this.pairs = pairs;
}
@Override
public int getCount() {
return pairs.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) {
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = LayoutInflater.from(context_1).inflate(
R.layout.custom_row, null);
viewHolder = new ViewHolder();
viewHolder.img = (ImageView) convertView
.findViewById(R.id.log_img);
viewHolder.txt = (TextView) convertView
.findViewById(R.id.tv_view);
/**
* At very first time when the List View row Item control's
* instance is created it will be store in the convertView as a
* ViewHolder Class object for the reusability purpose
**/
convertView.setTag(viewHolder);
} else {
/**
* Once the instance of the row item's control it will use from
* already created controls which are stored in convertView as a
* ViewHolder Instance
* */
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.txt.setText(pairs.get(position).name);
int id = context_1.getResources().getIdentifier(
pairs.get(position).img, "drawable",
context_1.getPackageName());
viewHolder.img.setImageResource(id);
return convertView;
}
public class ViewHolder {
public final ImageView img;
public final TextView txt;
}
}
Custom Adapter ListView Error
You need to pass Context
not ValueEventListener
so change adapter as
public customAdapter(/*ValueEventListener*/ Context context, int layoutResource,
List<UserInformation> userInformationsList) {
super(context, layoutResource, userInformationsList);
}
and remove the cast as well
customAdapter customAdapterIntent= new customAdapter(/*(ValueEventListener)*/ this,R.layout.userslist,userInformationsList);
where context
is required by the layoutinflater
or adapter to access the resources when you call getContext()
and also remove setContentView(R.layout.activity_search);
from list
method, you are doing it twice , so no need
Thank so much, I did as you said and It works but it only list the last user's information
You need to fetch all the users and add them in list
because currently you are storing information of last user in as string values and using those values to create list of single user object.
// outside onCreate
List<UserInformation> users = new ArrayList<>();
mRefresh.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DatabaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
listClean();
FirebaseUser user = mAuth.getCurrentUser();
userID = user.getUid();
Lat = dataSnapshot.child("Users").child(userID).child("Coordenates/Rute/Lat").getValue(String.class);
Lng = dataSnapshot.child("Users").child(userID).child("Coordenates/Rute/Lng").getValue(String.class);
DataSnapshot dS = dataSnapshot.child("Coordenate").child(Lat).child(Lng);
for(DataSnapshot Ds : dS.getChildren()) {
Object key = Ds.getKey();
String StringKey = String.valueOf(key);
// fetch the user Object based on key and add it to list
users.add(lidataSnapshot.child("Users").child(StringKey).getValue(UserInformation.class));
}
// now display list with all user information
customAdapter customAdapterIntent= new customAdapter(SearchActivity.this,
R.layout.userslist,
users);
mListView.setAdapter(customAdapterIntent);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(SearchActivity.this,"Error 404",Toast.LENGTH_SHORT).show();
}
});
}
});
Related Topics
Method to Refresh Fragment Content When Data Changed ( Like Recall Oncreateview)
How to Set Spinner Default by Its Value Instead of Position
Cart Item Count Increment/Decrement & Add to Cart
How to Resolve Javax.Xml.Bind.Jaxbcontext in Eclipse
How to Make a Textview Automatically Scroll as I Add More Lines of Text
Android Set Height and Width of Custom View Programmatically
Check If an Email Exists Before Creating a User Firebase Android
Play Store Alpha Test Download Link Not Working
How to Change the Icon Color Selected on Bottom Navigation Bar in Android Studio
How to Disable Preveious Date in a Date Picker
How to Open Fragment from Recyclerview Adapter
Android Q, Programmatically Connect to Different Wifi Ap for Internet
Showing Thumbnail for Link in Whatsapp || Og:Image Meta-Tag Doesn't Work
Install_Failed_User_Restricted:Android Studio Using Redmi 4 Device
Android - Edittext Not Showing Any Text