Paul
Paul

Reputation: 149

How to create custom adapter for custom listview with Hashmap

How i can create a custom adapter for this xml.Can someone guide me on how to create a custom adapter or give me a sample code on how to do it. Please help me i need to learn how to create custom adapter.Help me please. Thanks in advance.

This is my MainActivity.java

package com.example.work.listviewadapter;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class MainActivity extends ActionBarActivity {

private static final String PRODUCTLIST_URL ="http://192.168.56.1/productlist.php";


private ProgressDialog pDialog;

public  static  final JSONParser jParser = new JSONParser();

private static final String GET_PRODUCT = "message";

private static final String GET_ID = "ID";

private static final String GET_BRAND = "Brand";

private static final String GET_CATEGORY = "Category";

private static final String GET_DESCRIPTION = "Description";

private static final String GET_CODE = "Code";

private static final String GET_QUANTITY = "Quantity";

private static final String GET_UNIT = "Unit";

private static final String GET_UNITPRICE = "Unitprice";

private JSONArray order = null;

ListView list;
private ArrayList<HashMap<String, String>> orderlist;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.productlist);

new LoadComments().execute();


}


public void updateJSONdata() {

    orderlist = new ArrayList<HashMap<String, String>>();


    JSONObject json = jParser.getJSONFromUrl(PRODUCTLIST_URL);


    try {


        order = json.getJSONArray(GET_PRODUCT);

        for (int i = 0; i < order.length(); i++) {

            JSONObject c = order.getJSONObject(i);

            String id = c.getString(GET_ID);

            String brand = c.getString(GET_BRAND);

            String category = c.getString(GET_CATEGORY);

            String description = c.getString(GET_DESCRIPTION);

            String code = c.getString(GET_CODE);

            String quantity = c.getString(GET_QUANTITY);

            String unit = c.getString(GET_UNIT);

            String unitprice = c.getString(GET_UNITPRICE);



            HashMap<String, String> map = new HashMap<String, String>();

            map.put(GET_ID,id);

            map.put(GET_BRAND, brand);

            map.put(GET_CATEGORY, category);

            map.put(GET_DESCRIPTION, description);

            map.put(GET_CODE, code);

            map.put(GET_QUANTITY, quantity);

            map.put(GET_UNIT, unit);

            map.put(GET_UNITPRICE, unitprice);


            orderlist.add(map);

            }

    } catch (JSONException e) {

        e.printStackTrace();

    }

}

private void updateList() {

    //this is for my custom listview

}

final  public class LoadComments extends AsyncTask<Void, Void, Boolean> {

    @Override

    protected void onPreExecute() {

        super.onPreExecute();

        pDialog = new ProgressDialog(MainActivity.this);

        pDialog.setMessage("Loading Order...");

        pDialog.setIndeterminate(false);

        pDialog.setCancelable(true);

        pDialog.show();

    }

    @Override

    protected Boolean doInBackground(Void... arg0) {

        //we will develop this method in version 2

        updateJSONdata();

        return null;

    }

    @Override

    protected void onPostExecute(Boolean result) {

        super.onPostExecute(result);

        pDialog.dismiss();

        //we will develop this method in version 2

        updateList();

    }

}

}

This is my Custom ListView.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dip"
android:background="@drawable/list_selector"
>


<TextView
    android:id="@+id/Quantity"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="10000"
    android:textSize="24dip"
    android:textStyle="bold"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:layout_marginTop="24dp"
    android:layout_marginRight="51dp"
    >
</TextView>

<TextView
    android:id="@+id/Unit"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Gal."
    android:layout_alignParentRight="true"
    android:layout_marginTop="26dp"
    android:textSize="20dp"
    android:layout_marginRight="15dp"
    />

<TextView
    android:id="@+id/Description"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:text="White"
    android:textColor="#040404"
    android:typeface="sans"
    android:textSize="20dip"
    android:textStyle="bold"/>

<TextView
    android:id="@+id/Code"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Wpu-01"
    android:layout_marginTop="2dp"
    android:layout_below="@+id/Description"
    android:layout_marginLeft="10dp"/>
<TextView
    android:id="@+id/Brand"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/Code"
    android:layout_marginLeft="10dp"
    android:layout_marginTop="2dp"
    android:text="Weber"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Urethane"
    android:layout_below="@+id/Code"
    android:layout_marginTop="2dp"
    android:layout_toRightOf="@+id/Brand"
    android:layout_marginLeft="5dp"
    android:id="@+id/Category" />
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/Category"
    android:text="P"
    android:layout_marginLeft="12dp"
    android:paddingRight="5dp"
    android:layout_marginTop="2dp"
    android:layout_marginBottom="2dp"
    android:textStyle="italic"
    android:id="@+id/P"
    />
<TextView
    android:id="@+id/Price"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="10000.00"
    android:layout_below="@+id/Brand"
    android:layout_toRightOf="@+id/P"
    android:layout_marginTop="2dp"
    android:layout_marginLeft="2dp"
    />
<TextView
    android:id="@+id/ID"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="11"
    android:layout_alignParentRight="true"
    android:visibility="invisible"
    />
</RelativeLayout>

This for the listview

<?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">


<EditText
    android:id="@+id/search"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:hint="Search"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:singleLine="true"/>

<ListView
    android:layout_below="@+id/search"
    android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#fff"
    android:divider="#ff5873ff"
    android:dividerHeight="3dp" />

Upvotes: 0

Views: 1578

Answers (2)

Durgesh Patel
Durgesh Patel

Reputation: 1105

You can design your BaseAdapter like below code, also you can optimize listview performance using ViewHolder pattern

private class MyAdapter extends BaseAdapter{
    private LayoutInflater mlayoutInflater;

    public MyAdapter(Context context) {
        mlayoutInflater = LayoutInflater.from(context);  //Dynamic layout mapping
    }

    @Override
    public int getCount() {
        return orderlist.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) {
        convertView = mlayoutInflater.inflate(R.layout.listitem, null);  //  According to the layout of the document to instantiate view
        TextView tv = (TextView)convertView.findViewById(R.id.textView);
        tv.setText(orderlist.get(position).get(GET_BRAND).toString());
        return convertView;
    }
}

Upvotes: 2

Mauker
Mauker

Reputation: 11487

I'll use a custom adapter I've made as an example. It may solve your problem if you follow the steps and shape it to your needs.

Final result

When you want to make a custom ListView, you have to write your own adapter. In this particular case I'm subclassing the BaseAdapter class.

This custom adapter will take hold of my data model, and will inflate the data to my ListView rows.

First, I'll create the XML of my custom row. You can see the code below.

item_mail.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="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test text"
        android:id="@+id/tv_mail"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/iv_icon"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:src="@android:drawable/ic_menu_report_image" />
</RelativeLayout>

Here I've created a row that displays a text and an image.

Now, I'll create my custom adapter to handle this XML. As you can see below.

MailAdapter.java

public class MailAdapter extends BaseAdapter {

    private static final String LOG_TAG = MailAdapter.class.getSimpleName();

    private Context context_;
    private ArrayList<ArrayList<String>> mailitems;

    public MailAdapter(Context context, ArrayList<ArrayList<String>> mailitems) {
        this.context_ = context;
        this.mailitems = mailitems;
    }

    @Override
    public int getCount() {
        return mailitems.size();
    }

    @Override
    public Object getItem(int position) {
        return mailitems.get(position).get(0);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            LayoutInflater mInflater = (LayoutInflater)
                    context_.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);

            convertView = mInflater.inflate(R.layout.item_mail, null);
        }

        TextView tv_mail = (TextView) convertView.findViewById(R.id.tv_mail);
        ImageView iv_icon = (ImageView) convertView.findViewById(R.id.iv_icon);

        String mail = mailitems.get(position).get(0);
        String icon = mailitems.get(position).get(1);

        Log.d(LOG_TAG,"Mail: " + mail + " mail_icon: " + icon);

        tv_mail.setText(mail);
        // iv_icon.setImageURI(); Here you can do whatever logic you want to update your image, using URI's, ID's, or something else.

        return convertView;
    }
}

Ok. Now we have everything to make this work. In your Activity class, do something like that:

activity_main.xml

<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="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <TextView
        android:text="@string/hello_world"
        android:id="@+id/tv_header"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/tv_header">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Add mail"
            android:id="@+id/button"
            android:layout_gravity="center" />

        <ListView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/listView" />
    </LinearLayout>

</RelativeLayout>

MainActivity.java

public class MainActivity extends ActionBarActivity {

    private int numMail = 1; // Dummy int to create my items with different numbers.

    private MailAdapter mailAdapter; // Your custom adapter.

    private ArrayList<ArrayList<String>> mailItems; // This is going to be your data structure, everytime you change it, call the notifyDataSetChanged() method.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button bt = (Button) findViewById(R.id.button);
        ListView lv_mail = (ListView) findViewById(R.id.listView);
        mailItems = new ArrayList<>();
        mailAdapter = new MailAdapter(this,mailItems);
        lv_mail.setAdapter(mailAdapter);

        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addItem(); // The method I'm using to insert the item. Look for it below.
            }
        });
    }

    // Here I'm creating a new ArrayList, and appending it to my 'mailItems' Array. After that, I'm notifying the adapter that my data changed.
    private void addItem() {
        ArrayList<String> mail = new ArrayList<>();

        mail.add(0,"mail " + numMail++);
        mail.add(1,"path_to_image"); // Depending on what you want to do, put your path, URI, or whatever other way you want to store that image data.

        mailItems.add(mail); // Inserting the data on the ArrayList.
        mailAdapter.notifyDataSetChanged(); // Notifying the adapter that my ArrayList was modified.
    }
}

This should do the trick.

You can read a little more about that here and I've found a similar question here, which you can read as well.

Edit: Another related question, which might be an interesting read.

Upvotes: 0

Related Questions