I am new to Android development. I am trying to make my custom listview items layout. I want to know how will I give image path if I have a ImageView in may layout.
Activity file where I am populating this ListView
ListView lstItems = (ListView) findViewById(R.id.lstItems);
String[] from = new String[]{"itemname", "productimage"};
int[] to = new int[]{R.id.itemname, R.id.productimage};
List<HashMap<String, Object>> fillMaps = new ArrayList<HashMap<String, Object>>();
for (Item item : objects) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("itemname", item.getName());
map.put("productimage", item.getImages());
fillMaps.add(map);
}
SimpleAdapter adapter = new SimpleAdapter(this, fillMaps, R.layout.shop_listitem_view, from, to);
lstItems.setAdapter(adapter);
Layout file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:id="#+id/itemname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="19dp"
android:layout_marginTop="22dp"
android:text="TextView"
android:textSize="14sp"
android:layout_alignParentTop="true"
android:layout_toEndOf="#+id/productimage" />
<ImageView
android:id="#+id/productimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="21dp"
app:srcCompat="#drawable/common_full_open_on_phone"
android:layout_alignTop="#+id/itemname"
android:layout_alignParentStart="true" />
</RelativeLayout>
In this case, the SimpleAdapter will not work for you. In first place you have to create a class that represent your business logic:
public class Product {
public String productName;
public String productImage;
}
Second, you have to add the Glide library into your build.gradle (module app) file. Add this line in your dependencies block:
dependencies {
compile 'com.github.bumptech.glide:glide:3.7.0'
}
After that, you have to create your layout file that will be inflated by your Adapter:
<?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="match_parent">
<ImageView
android:id="#+id/your_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/your_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Now, let's create your Adapter class, it must extends the BaseAdapter class:
public class YourAdapter extends BaseAdapter{
private List<Object> products;
private Context context;
public YourAdapter(Context context, List<Product> products){
this.context = context;
this.products = products;
}
#Override
public int getCount() {
return products.size();
}
#Override
public Object getItem(int position) {
return products.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = li.inflate(R.layout.your_list_layout, null);//set layout for displaying items
ImageView image = (ImageView) view.findViewById(R.id.your_image_view);//get id for image view
Glide.with(context).load(products.get(position).productImage).into(image); //set the image in your image view
TextView text = (TextView) view.findViewById(R.id.your_text_view);
text.setText(products.get(position).productName);
return view;
}
}
And finally, in your activity you can use it:
//Create a product:
List<Product> p = new ArrayList<>();
Product prod = new Product();
prod.productName = "Name of your product";
prod.productImage = "http://your_image_url";
prod.add(prod);
YourAdapter adapter = new YourAdapter(this, p);
//and finally, set it into your listview:
listview.setAdapter(adater);
Related
I'm attempting to use a custom ArrayAdapter for a listView in which I have in one of my activities. The quantity of data I am using is quite large, so to rule out that being the issue I hardcoded an ArrayList<ArrayList<String>> to simply pass 8 items to display on my listView, however the same issue has occured where only the initial 4 are being displayed with no ability to scroll to further items.
I am also aware that there are currently no images being displayed on the listView, I intend to link this up after resolving this issue.
This is the main activity which will display the listView in question:
ProductSelectionActivity.java
public class ProductSelectionActivity extends AppCompatActivity {
ListView productListView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_selection);
ArrayList<ArrayList<String>> productsList = new ArrayList<ArrayList<String>>();
ArrayList<String> prodIds = new ArrayList<String>();
ArrayList<String> prodNames = new ArrayList<String>();
ArrayList<String> prodCosts = new ArrayList<String>();
ArrayList<String> prodMainImages = new ArrayList<String>();
prodIds.add("id1");
prodIds.add("id2");
prodIds.add("id3");
prodIds.add("id4");
prodIds.add("id5");
prodIds.add("id6");
prodIds.add("id7");
prodIds.add("id8");
prodNames.add("name1");
prodNames.add("name2");
prodNames.add("name3");
prodNames.add("name4");
prodNames.add("name5");
prodNames.add("name6");
prodNames.add("name7");
prodNames.add("name8");
prodCosts.add("cost1");
prodCosts.add("cost2");
prodCosts.add("cost3");
prodCosts.add("cost4");
prodCosts.add("cost5");
prodCosts.add("cost6");
prodCosts.add("cost7");
prodCosts.add("cost8");
prodMainImages.add("image1");
prodMainImages.add("image2");
prodMainImages.add("image3");
prodMainImages.add("image4");
prodMainImages.add("image5");
prodMainImages.add("image6");
prodMainImages.add("image7");
prodMainImages.add("image8");
productsList.add(prodIds);
productsList.add(prodNames);
productsList.add(prodCosts);
productsList.add(prodMainImages);
// Create the listView arrayAdapter
ProductListAdapter arrayAdapter =
new ProductListAdapter(this, R.layout.product_list_items, productsList);
// Set the adapter
productListView = (ListView) findViewById(R.id.products_list);
productListView.setAdapter(arrayAdapter);
}}
The following is the class for the adapter:
ProductListAdapter.java
public class ProductListAdapter extends ArrayAdapter<ArrayList<String>> {
// Initialise list of products
ArrayList<ArrayList<String>> products;
public ProductListAdapter(Context context, int resource, ArrayList<ArrayList<String>> objects) {
super(context, resource, objects);
products = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.product_list_items, parent, false);
}
// Get product listing info with reference to position that has been passed as param
ArrayList<String> prodIds = products.get(0);
String prodId = prodIds.get(position);
ArrayList<String> prodNames = products.get(1);
String prodName = prodNames.get(position);
ArrayList<String> prodCosts = products.get(2);
String prodCost = prodCosts.get(position);
ArrayList<String> prodMainImages = products.get(3);
String prodMainImage = prodMainImages.get(position);
// Getting id for textview and imageview
TextView textViewName = (TextView) convertView.findViewById(R.id.prod_name_text);
TextView textViewCost = (TextView) convertView.findViewById(R.id.prod_cost_text);
// Setting values to ids
textViewName.setText(prodName);
textViewCost.setText("£"+prodCost);
return convertView;
}}
The layout for the ProductSelectionActivity:
activity_product_selection.xml
<android.support.constraint.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="match_parent"
android:layout_height="match_parent"
tools:context=".ProductSelectionActivity">
<ListView
android:id="#+id/products_list"
android:layout_width="396dp"
android:layout_height="508dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.961" />
</android.support.constraint.ConstraintLayout>
The layout for the adapter:
product_list_items.xml
<LinearLayout 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="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:orientation="horizontal"
android:weightSum="100" >
<ImageView
android:id="#+id/prod_main_image"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_weight="60"
app:srcCompat="#color/background_holo_light" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="40"
android:orientation="vertical" >
<TextView
android:id="#+id/prod_name_text"
android:layout_width="278dp"
android:layout_height="60dp"
android:text="#string/prod_name_text" />
<TextView
android:id="#+id/prod_cost_text"
android:layout_width="278dp"
android:layout_height="60dp"
android:text="#string/prod_cost_text" />
</LinearLayout>
</LinearLayout>
I believe the issue lies within the layout files, through process of elimination of other factors that I thought may have been the issue; such as ensuring all data was being passed correctly (I was able to identify this through the Logcat).
If there is anything else that I could clarify then please let me know.
The ListView will display the items that you are passing in the adapter. So you are passing an ArrayList of 4 elements. This is why the ListView only shows 4 items. If you add more elements to the productsList ArrayList then the number of items you can show will increase.
Another thing, just to improve on what you are doing. Instead of creating separate ArrayLists for each product detail separately, just create a model for your Product and load it with data. Then pass a ArrayList to your custom adapter with any number of Product items you want.
class Product {
String productId;
String productName;
String productCost;
String productImage;
Product(String id, String name, String cost, String image) {
productId = id;
productName = name;
productCost = cost;
productImage = image;
}
}
Now in your ProductSelectionActivity just use it like this.
ArrayList<Product> productList = new ArrayList();
productList.add(new Product("id1", "name1", "cost1", "image1");
//Do this for all other products
ProductListAdapter arrayAdapter = new ProductListAdapter(this, R.layout.product_list_items, productList);
// Set the adapter
productListView = (ListView) findViewById(R.id.products_list);
productListView.setAdapter(arrayAdapter);
The final step is to update your adapter to handle an ArrayList of Products
public class ProductListAdapter extends ArrayAdapter<Product> {
// Initialise list of products
ArrayList<Product> products;
public ProductListAdapter(Context context, int resource, ArrayList<Product> objects) {
super(context, resource, objects);
products = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.product_list_items, parent, false);
}
//Get the product item for this position
Product product = products.get(0);
TextView textViewName = (TextView) convertView.findViewById(R.id.prod_name_text);
TextView textViewCost = (TextView) convertView.findViewById(R.id.prod_cost_text);
// Setting values to ids
textViewName.setText(product.productName);
textViewCost.setText("£" + product.productCost);
return convertView;
}
}
Another improvement would be to use a ViewHolder instead of using a simple view.
You can create a Wrapper(POJO) class to hold your product information and use it for your list adapter. It would be a better way to handle by you list rather than using ArrayList<ArrayList<String>>.
First create a model(Pojo) class to hold product information.
class Product {
String prodId;
String prodName;
String prodCost;
String prodMainImage;
public Product(String prodIds, String prodNames, String prodCostsl, String prodMainImages) {
this.prodId = prodIds;
this.prodName = prodNames;
this.prodCost = prodCostsl;
this.prodMainImage = prodMainImages;
}
}
ProductSelectionActivity.java
public class ProductSelectionActivity extends AppCompatActivity {
ListView productListView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_selection);
ArrayList<Product> productsList = new ArrayList<>();
productsList.add(new Product("id1", "name1", "cost1", "image1"));
productsList.add(new Product("id2", "name2", "cost2", "image2"));
productsList.add(new Product("id3", "name3", "cost3", "image3"));
productsList.add(new Product("id4", "name4", "cost4", "image4"));
ProductListAdapter arrayAdapter =
new ProductListAdapter(this, R.layout.product_list_items, productsList);
// Set the adapter
productListView = (ListView) findViewById(R.id.products_list);
productListView.setAdapter(arrayAdapter);
}}
ProductListAdapter.java
public class ProductListAdapter extends ArrayAdapter<Product> {
// Initialise list of products
ArrayList<Product> products;
public ProductListAdapter(Context context, int resource, ArrayList<Product> objects) {
super(context, resource, objects);
products = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.product_list_items, parent, false);
}
Product product = products.get(position);
// Getting id for textview and imageview
TextView textViewName = convertView.findViewById(R.id.prod_name_text);
TextView textViewCost = convertView.findViewById(R.id.prod_cost_text);
// Setting values to ids
textViewName.setText(product.prodName);
textViewCost.setText("£"+product.prodCost);
return convertView;
}
}
That's it. It should work properly. Although nowadays, RecyclerView is being used more for its performance and management. This code can be replaced with RecyclerView as well. Let me know if you want to convert it to RecyclerView. I can help you with that.
Man, first of all use RecyclerView and don't worry about size of data. Secondly make a class which will contains your data:
class Data {
int id;
String name;
String imageUrl;
public Data(int id, String name, String imageUrl) {
this.id = id;
this.name = name;
this.imageUrl = imageUrl;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getImageUrl() {
return imageUrl;
}
}
Please, research information about how to use RecyclerView and why RecyclerView is better that ListView.
Set wrap_content to the height of root layout in product_list_items layout
<LinearLayout 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="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:orientation="horizontal"
android:weightSum="100" >
<ImageView
android:id="#+id/prod_main_image"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_weight="60"
app:srcCompat="#color/background_holo_light" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="40"
android:orientation="vertical" >
<TextView
android:id="#+id/prod_name_text"
android:layout_width="278dp"
android:layout_height="60dp"
android:text="#string/prod_name_text" />
<TextView
android:id="#+id/prod_cost_text"
android:layout_width="278dp"
android:layout_height="60dp"
android:text="#string/prod_cost_text" />
</LinearLayout>
I want to display 3 fields from the database, but I do not know about simple_list_item_1
SQLiteDatabase db = dbcenter.getReadableDatabase();
cursor = db.rawQuery("SELECT * FROM TABLE", null);
daftar = new String[cursor.getCount()];
cursor.moveToFirst();
for (int cc = 0; cc < cursor.getCount(); cc++) {
cursor.moveToPosition(cc);
daftar[cc] = cursor.getString(1).toString();
}
ListView01 = (ListView) view.findViewById(R.id.listView1);
ListView01.setAdapter(new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, daftar));
ListView01.setSelected(true);
In the above view is the code displays the data from the table, but only one field appears.
Can you give me an example, to replace it into modified list_item with 3 <TextView> with java code
you can create a custom list view with 3 text view
now custom_list_view layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/name"
android:text="#string/name"
android:textSize="20sp"
android:layout_marginTop="19dp"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/price"
android:layout_toStartOf="#+id/price"
android:layout_marginRight="30dp"
android:layout_marginEnd="30dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/price"
android:text="Price"
android:textSize="20sp"
android:layout_alignBaseline="#+id/name"
android:layout_alignBottom="#+id/name"
android:layout_centerHorizontal="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/stock"
android:text="Stock"
android:textSize="20sp"
android:layout_alignBaseline="#+id/price"
android:layout_alignBottom="#+id/price"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="81dp"
android:layout_marginEnd="81dp"/>
</RelativeLayout>
Create List View in layout , i created in mainactivity layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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="match_parent"
android:layout_height="match_parent"
tools:context="com.pro.salman.customlistview.MainActivity">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/list_item"/>
</RelativeLayout>
Custom List View Class
public class CustomListView extends BaseAdapter {
private ArrayList<HashMap<String,String>> list;
private LayoutInflater mLayoutInflater;
private Context mContext;
public CustomListView(ArrayList<HashMap<String,String>> list,Context c) {
this.list = list;
this.mContext = c;
mLayoutInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = mLayoutInflater.inflate(R.layout.custom_list_view,parent,false);
Holder h = new Holder();
// set id's
h.name = (TextView)(view.findViewById(R.id.name));
h.price = (TextView)(view.findViewById(R.id.price));
h.stock = (TextView)(view.findViewById(R.id.stock));
HashMap<String,String> hashMap = new HashMap<>();
hashMap = list.get(position);
h.name.setText(hashMap.get("nameKey"));
h.price.setText(hashMap.get("priceKey"));
h.stock.setText(hashMap.get("stockKey"));
return view;
}
private class Holder
{
TextView name;
TextView price;
TextView stock;
}
}
And Now in mainactivity class
public class MainActivity extends AppCompatActivity {
private ListView mListView;
private ArrayList<HashMap<String,String>> mArrayList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mArrayList = new ArrayList<HashMap<String, String>>();
for(int i =0;i<20;i++)
{
HashMap<String,String> mHashMap = new HashMap<>();
mHashMap.put("nameKey","name "+String.valueOf(i));
mHashMap.put("priceKey","price "+String.valueOf(i));
mHashMap.put("stockKey","stock "+String.valueOf(i));
mArrayList.add(mHashMap);
}
mListView = (ListView)(findViewById(R.id.list_item));
CustomListView customListView = new CustomListView(mArrayList,this);
mListView.setAdapter(customListView);
}
}
Result
When you call new ArrayAdapter(..., android.R.layout.simple_list_item_1, ...), you're telling the system to use android.R.layout.simple_list_item_1 for your data. If that doesn't work, there's really only one option: handle inflating and populating the view yourself. You'd do that by creating a custom subclass of ArrayAdapter and overriding onCreateView().
Official documentation: https://developer.android.com/reference/android/widget/ArrayAdapter.html
You may also customize what type of view is used for the data object in the collection. To customize what type of view is used for the data object, override getView(int, View, ViewGroup) and inflate a view resource.
create a xml named custom_layout like
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="16sp" >
</TextView>
Use like R.layout.custom_layout instead of android.R.layout.simple_list_item_1
I have a listview which contents of different post. My current post limit per page load is 25. Each post is of different size. I want ListView size upto those 25 objects, i.e., it should accomodate all the objects from listadapter.
I have currently set my listview size as following.
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="5000sp" >
</ListView>
My ListAdapter is set as:
ListAdapter adapter = new SimpleAdapter(NewsFeed.this, contactList,
R.layout.list_item, new String[] { TAG_MESSAGE,
TAG_CREATETIME }, new int[] { R.id.message,
R.id.time });
setListAdapter(adapter);
list_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:orientation="vertical"
android:paddingTop="#dimen/activity_vertical_margin" >
<TextView
android:id="#+id/time"
android:gravity="right"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textColor="#b1b1b1"
android:background="#abc0e3" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/cover" />
<TextView
android:id="#+id/message"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/imageView1"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:text="TextView"
android:linksClickable="true"
android:autoLink="web" />
</LinearLayout>
see if this works for you, where you adjust the width then you can decide on what width to use based on the text length,
/* create an inline class that defines each item in the list
private class Post
{
String time;
String message;
Bitmap bmp;
public String getTime(){return time;}
public String getMessage(){return message;}
public Bitmap getBitmap(){return bmp;}
}
//** populate your array with each item in list
ArrayList<Post> array = new ArrayList<Post>();
Post p = new Post();
//* ..............
ListAdapter adapter = new ListAdapter (this, array);
listView.setAdapter(adapter);
private class ListAdapter extends BaseAdapter
{
Context context;
ArrayList<Post> contactList;
public ListAdapter(Context context, ArrayList<Post> contactList)
{
this.context = context;
this.contactList = contactList;
}
public View getView(int position, View convertView, ViewGroup parent)
{
try
{
if(convertView==null)
{
LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(R.layout.list_item, parent, false);
}
ImageView imageView = (ImageView) convertView.findViewById(R.id.imageView1);
TextView timeview = (TextView) convertView.findViewById(R.id.time);
TextView msgview = (TextView) convertView.findViewById(R.id.message);
Post post = getItem(position);
imageView.setImageBitmap(post.getBitmap());
timeView.setText(post.getTime());
messageView.setText(post.getMessage());
int width = convertView.getWidth();
int height = convertView.getHeight();
int messageWidth = post.getMessage().length();
//* adjust the width based on your message width
//* width = ........ do something here
//* set the desired width here
convertView.setLayoutParams(new LayoutParams(width, height));
return convertView;
}
catch(Exception e)
{
}
return null;
}
#Override
public int getCount()
{
return contactList.size();
}
#Override
public Post getItem(int position)
{
return contactList.get(position);
}
#Override
public long getItemId(int position)
{
return 0;
}
}
Change code in list_item.xml
android:layout_width="wrap_content" to fill_parent or match_parent
Hi guys, I tried to learn how to use custom ListView by this page
It works fine but I have problems with another options.
Cannot set margin to listItems
Cannot set backgro
Cannot set OnItemClickListener
1# Margin
First of all I'm trying to set margin between list items but nothing works. I try to set margin on RelativeLayout in rowlayout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="75dp"
android:background="#drawable/rounded"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
>
2# Background
I want to set background on whole screen under listView. I think I put black color on every View in every xml I found but nothing affect the background. I can change background of single list items, that's all.
android:background="#000000"
3#OnItemClickListener
My last problem is that I'm not able to set onItemClickListener. I have no idea how to set it if I don't have simply ListView but RelativeLayout with TextView etc.
I guess I have to use
setOnClickListener(new OnClickListener()
and after that
public void onClick(View arg0) {
but I have no idea on which View I have to use this method.
Files
MyAdapter.java
public class MyAdapter extends ArrayAdapter<Model> {
private final Context context;
private final ArrayList<Model> modelsArrayList;
public MyAdapter(Context context, ArrayList<Model> modelsArrayList) {
super(context, R.layout.rowlayout, modelsArrayList);
this.context = context;
this.modelsArrayList = modelsArrayList;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// 1. Create inflater
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// 2. Get rowView from inflater
View rowView = null;
if(!modelsArrayList.get(position).isGroupHeader()){
rowView = inflater.inflate(R.layout.rowlayout, parent, false);
// 3. Get icon,title & counter views from the rowView
ImageView imgView = (ImageView) rowView.findViewById(R.id.item_icon);
TextView titleView = (TextView) rowView.findViewById(R.id.item_title);
TextView counterView = (TextView) rowView.findViewById(R.id.item_counter);
// 4. Set the text for textView
imgView.setImageResource(modelsArrayList.get(position).getIcon());
titleView.setText(modelsArrayList.get(position).getTitle());
counterView.setText(modelsArrayList.get(position).getCounter());
}
else{
//rowView = inflater.inflate(R.layout.group_header, parent, false);
// TextView titleView = (TextView) rowView.findViewById(R.id.header);
// titleView.setText(modelsArrayList.get(position).getTitle());
}
// 5. retrn rowView
return rowView;
}
}
Model.java
package com.example.sunny.katan;
/**
* Created by Sunny on 15.09.14.
*/
public class Model{
private int icon;
private String title;
private String counter;
private boolean isGroupHeader = false;
public Model(String title) {
this(-1,title,null);
isGroupHeader = true;
}
public Model(int icon, String title, String counter) {
super();
this.icon = icon;
this.title = title;
this.counter = counter;
}
public String getCounter() {
return counter;
}
public String getTitle() {
return title;
}
public int getIcon() {
return icon;
}
public boolean isGroupHeader() {
return false;
}
public void setGroupHeader(boolean isGroupHeader) {
this.isGroupHeader = isGroupHeader;
}
//gettters & setters...
}
main.java
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// if extending Activity
//setContentView(R.layout.activity_main);
// 1. pass context and data to the custom adapter
MyAdapter adapter = new MyAdapter(this, generateData());
// if extending Activity 2. Get ListView from activity_main.xml
//ListView listView = (ListView) findViewById(R.id.listview);
// 3. setListAdapter
//listView.setAdapter(adapter); if extending Activity
setListAdapter(adapter);
}
private ArrayList<Model> generateData(){
ArrayList<Model> models = new ArrayList<Model>();
models.add(new Model(R.raw.barbell,"Cviky","37"));
models.add(new Model(R.raw.stretching,"Protahování","94"));
models.add(new Model(R.raw.work,"Generování workoutu","293"));
return models;
}
rowlayout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="75dp"
android:background="#drawable/rounded"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
>
<!-- icon -->
<ImageView
android:id="#+id/item_icon"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_centerVertical="true"
android:src="#raw/barbell"
/>
<!-- title -->
<TextView
android:id="#+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_toRightOf="#+id/item_icon"
android:layout_marginTop="30dp"
android:layout_alignBaseline="#+id/item_counter"
android:textSize="20dp"
/>
<!-- counter -->
<TextView
android:id="#+id/item_counter"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignParentRight="true"
android:layout_marginRight="8dp"
android:layout_centerVertical="true"
android:background="#drawable/rectangle"
android:gravity="center"
android:textColor="#FFFFFF"
android:textSize="12sp"
android:textStyle="bold" />
</RelativeLayout>
main.xml
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="false"
>
<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".katan_lobby"
android:orientation="vertical"
>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/menu"
android:layout_gravity="center_horizontal"
android:background="#238CD4"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/prvniItemSeznamu"
android:background="#238CD4"
style="#style/listView"
/>
</LinearLayout>
</ScrollView>
Looks like you are half way there in your activity.
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
MyAdapter adapter = new MyAdapter(this, generateData());
ListView listView = (ListView) findViewById(R.id.menu);
listView.setAdapter(adapter); if extending Activity
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
onItemClick(AdapterView<?> parent, View view, int position, long id)
{
//You now have the position but you will need to get your model list and use .get(position) and cast it to Model to get access to it.
}
});
}
//First define your list view item xml… something like this.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/white"
android:layout_marginTop="10dp"
android:padding="10dp" >
<TextView
android:id="#+id/item1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/custom_blue"
android:text="TextView" />
<TextView
android:id="#+id/item2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="#color/custom_grey"
android:text="TextView" />
</LinearLayout>
//Then you define your list list adapter.
public class MyListAdapter extends ArrayAdapter<MyModel> {
private Context context;
private ArrayList<MyModel> myModel;
public MyListAdapter(Context context, ArrayList<MyModel> myModelList) {
super(context, R.id.icon, myModelList);
this.context = context;
this.myModelList = myModelList;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = null;
View rowView = convertView;
TextView myItemName = (TextView)rowView.findViewById(R.id.item1);
TextView myItemTitle = (TextView)rowView.findViewById(R.id.item2);
//use your models getters/setters
myItemName.setText(myModelList.get(position).getItemTitle());
myItemTitle.setText(myModelList.get(position).getItemName());
return rowView
}
}
//Now use both the list adapter and list item in your ListFragment or ListActivity.
ArrayList<MyModel> myModelList = new ArrayList<MyModel>();
MyListAdapter myApt = new MyListAdapter(this, myModelList);
setListAdapter(myApt);
//For clicking on the items:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// ListView Clicked item value
String itemValue = l.getItemAtPosition(position).toString();
doSomethingWihtMyItemMethod(position);
}
/* You can customize your list item anyway you like, just be aware of screen real estate when doing so.Hope this helps. */
I created this class called GeoArea, which is suppose to store "Geographical Area" that have children Geographical Areas, this is fairly strait foward:
public class GeoArea {
public String id;
public String name;
public List<GeoArea> subGeoAreas;
public GeoArea parentGeoArea;
public GeoArea(String id) {
this.id = id;
name = id;
subGeoAreas = new LinkedList<GeoArea>();
}
#Override
public String toString() {
return name;
}
}
I have created the following Layout to render it on Android, the idea here is to for each GeoArea to recursively render it self and then it's children GeoArea in a listView:
//layout_geo_area.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/txtGeoAreaName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:gravity="left"
android:text="Geo Area Name"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ListView
android:id="#+id/listViewChildGeoAreas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/txtGeoAreaName"
android:gravity="left" >
</ListView>
</RelativeLayout>
This is my adapter I created for GeoArea to be displayed in a listView:
public class AdapterGeoArea extends ArrayAdapter<GeoArea>{
private ArrayList<GeoArea> _myGeoArea;
private Context _myContext;
LayoutInflater _inflater;
public AdapterGeoArea(Context context, ArrayList<GeoArea> myGeoArea) {
super(context, 0, myGeoArea);
_myGeoArea = myGeoArea;
_inflater = LayoutInflater.from(context);
_myContext = context;
}
public int getCount() {
return _myGeoArea.size();
}
public View getView(int position, View convertView, ViewGroup parent) {
GeoAreaLayoutHolder holder;
if (convertView == null) {
convertView = _inflater.inflate(R.layout.layout_geo_area,parent,false);
holder = new GeoAreaLayoutHolder();
holder.txtGeoAreaName = (TextView)convertView.findViewById(R.id.txtGeoAreaName);
holder.txtGeoAreaName.setTag(convertView);
holder.listViewChildGeoAreas = (ListView)convertView.findViewById(R.id.listViewChildGeoAreas);
holder.listViewChildGeoAreas.setTag(convertView);
} else {
holder = (GeoAreaLayoutHolder) convertView.getTag();
}
GeoArea curGeoArea = _myGeoArea.get(position);
holder.txtGeoAreaName.setText(curGeoArea.name);
if(curGeoArea.subGeoAreas.size()>0){
ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
AdapterGeoArea adapter = new AdapterGeoArea(_myContext, testList);
for(GeoArea childGeoArea:curGeoArea.subGeoAreas){
testList.add(childGeoArea);
}
holder.listViewChildGeoAreas.setAdapter(adapter);
}
return convertView;
}
static class GeoAreaLayoutHolder {
public TextView txtGeoAreaName;
public ListView listViewChildGeoAreas;
}
}
And here is my Activity that I am using to set it all up:
public class ActivityGeoAreas extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_geo_area);
GeoArea.searchTerm = "Bar & Grill";
GeoArea torontoArea = new GeoArea("cityOfToronto");
ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
testList.add(torontoArea);
AdapterGeoArea adapter = new AdapterGeoArea(this, testList);
ListView lv = (ListView) findViewById(R.id.listViewChildGeoAreas);
lv.setAdapter(adapter);
}
}
When I try to run it, I get the error nullPointerException on the line:
holder.txtGeoAreaName.setText(curGeoArea.name);
What am I doing wrong?
You may want to check ExpandableListView may suit your needs better
http://developer.android.com/reference/android/widget/ExpandableListView.html
An example # http://www.androidhive.info/2013/07/android-expandable-list-view-tutorial/
Continuing from my previous answer to your question ( i though that solved your problem)
To display just name in your listview
list_row.xml // this is the layout with textview to be inflated in getView.
Each row will have textview
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/textGeoArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="14dp"
android:text="Choose Area"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
layout_geo_area.xml // with only listview no textview
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/listViewChildGeoAreas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:gravity="left" >
</ListView>
</RelativeLayout>
Now your adapter class
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_row,parent,false);
// inflate list_row.xml with textview
holder = new ViewHolder();
holder.tv = (TextView)convertView.findViewById(R.id.textGeoArea);
holder.setTag(convertView);
}
else {
holder = (ViewHolder) convertView.getTag();
}
GeoArea curGeoArea = _myGeoArea.get(position);
holder.tv.setText(curGeoArea.name);
return convertView;
}
static class ViewHolder // use a view holder for smooth scrolling an performance
{
TextView tv;
}
You have a custom adapter.
public class AdapterGeoArea extends ArrayAdapter<GeoArea>{
Now you set the adapter to listview like below
AdapterGeoArea adapter = new AdapterGeoArea(this, testList);
ListView lv = (ListView) findViewById(R.id.listViewChildGeoAreas);
lv.setAdapter(adapter);
So why do you need the below. remove these
if(curGeoArea.subGeoAreas.size()>0){
ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
AdapterGeoArea adapter = new AdapterGeoArea(_myContext, testList);
for(GeoArea childGeoArea:curGeoArea.subGeoAreas){
testList.add(childGeoArea);
}
holder.listViewChildGeoAreas.setAdapter(adapter);