Search code examples
androidlistviewcustom-adapter

Change icon in listview


I am trying to change the icon of the custom listview but it keeps crashing. How do i change the icon for each page ? for example:

I tried adding the Icon in the Forloop but that just makes it crash, i also tried to google it, but couldnt find anything that fixed my problem. Also i only recently started developing android. So i dont have much knowledge about this.

This is the "Text page" it has the icon set as a text icon.

Text Page

This is the "News page" i would like it to have the News icon but now its like this:

News Page

This is my code that i use to generate the "Text Page"

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.comp_cont_bar);

    ListView lv = (ListView) findViewById(R.id.lv1);
    registerForContextMenu(lv);

    mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipelayout);

    mSwipeRefreshLayout.setOnRefreshListener(
            new SwipeRefreshLayout.OnRefreshListener() {
                @Override
                public void onRefresh() {
                finish();
                startActivity(getIntent());
                }
            }
    );

    try {
    APIClient api = new APIClient();
    JSONArray result = null;

    try {
        result = api.execute("http://test.soundwave.drieo.nl/api/content" + apikey).get();
    }
    catch (Exception e) {
       e.printStackTrace();
    }

    List<CustomListView> contents = new ArrayList<CustomListView>();

    for(int i = 0; i < result.length(); i++){
        try {
            JSONObject row = result.getJSONObject(i);

            String content = row.optString("FormattedName");
            String content2 = row.optString("CreatedBy");
            String content3 = row.optString("Id");

            CustomListView item = new CustomListView();

            item.firstLine = content;
            item.description = content2;
            item.ID = content3;

            contents.add(item);

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

        ListAdapter theAdapter = new CustomAdapter(MainComp_Content.this, contents);
        ListView theListView = (ListView) findViewById(R.id.lv1);
        theListView.setAdapter(theAdapter);

        theListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {

                TextView textView = (TextView) view.findViewById(R.id.tbid);
                UID = textView.getText().toString();

                Intent intent = new Intent(MainComp_Content.this, MainComp_Content_edit.class);
                intent.putExtra("uid", UID);
                startActivity(intent);
            }
        });

        theListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                TextView textView = (TextView) view.findViewById(R.id.tbid);
                UID = textView.getText().toString();
                return false;
            }
        });

    } catch (Exception e) {
        e.printStackTrace();
    }

Custom adapter code (where i have declared the icon):

package nl.drieo.soundwave.test.cms;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

public class CustomAdapter extends ArrayAdapter<CustomListView> {
public CustomAdapter(Context context, List<CustomListView> contents) {
    super(context, R.layout.custom_row, contents);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater theInflater = LayoutInflater.from(getContext());

    View theView = theInflater.inflate(R.layout.custom_row, parent, false);

    CustomListView tvFirstItem = getItem(position);

    TextView theTextView = (TextView) theView.findViewById(R.id.firstLine);
    theTextView.setText(tvFirstItem.firstLine);

    TextView theTextView2 = (TextView) theView.findViewById(R.id.secondLine);
    theTextView2.setText(tvFirstItem.description);

    TextView theTextView3 = (TextView) theView.findViewById(R.id.tbid);
    theTextView3.setText(tvFirstItem.ID);

    ImageView theImageView = (ImageView) theView.findViewById(R.id.icon);
    theImageView.setImageResource(R.drawable.ic_content);

    return theView;
}
}

Solution

  • To answer your question, Yes there is better way to implement the same thing. For example, if for News and Test Page, Model is same, you can add one additional parameter like:

    public class CustomListView {
    
    // Along with your other properties
    
    private boolean isTestPage;
    
    public boolean isTestPage() {
        return isTestPage;
    }
    
    public void setIsTestPage(boolean isTestPage) {
        this.isTestPage = isTestPage;
    }
    }
    

    And then you can use the same CustomAdapter,

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater theInflater = LayoutInflater.from(getContext());
    
        View theView = theInflater.inflate(R.layout.custom_row, parent, false);
    
        CustomListView tvFirstItem = getItem(position);
    
        TextView theTextView = (TextView) theView.findViewById(R.id.firstLine);
        theTextView.setText(tvFirstItem.firstLine);
    
        TextView theTextView2 = (TextView) theView.findViewById(R.id.secondLine);
        theTextView2.setText(tvFirstItem.description);
    
        TextView theTextView3 = (TextView) theView.findViewById(R.id.tbid);
        theTextView3.setText(tvFirstItem.ID);
    
        ImageView theImageView = (ImageView) theView.findViewById(R.id.icon);
    
        if (tvFirstItem.isTestPage()) {
            // Test Page Image
            theImageView.setImageResource(R.drawable.ic_test_page);
        } else{
            // News Page Image
            theImageView.setImageResource(R.drawable.ic_news_page);
        }
    
        return theView;
    }
    

    Other solution when your Model isn't same for both of the two, then you can create a interface named CustomInterface and implement it to both of your models. Then in the adapter, instead of the model, use CustomInterface and in your getView, you have to check the current model like:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater theInflater = LayoutInflater.from(getContext());
        View theView = theInflater.inflate(R.layout.custom_row, parent, false);
        if(entity instanceof Obj1){
            // Test Page
        } else if(entity instanceof Obj2){
            // News Page
        }
        return theView;
    }
    

    Remember that, List works only for homogeneous collections. If you have heterogeneous collection, you can implement interface on all of the models and make a List of the interface and then can put any model within that list which implement same interface.

    But this one is really complicated solution. The simple and better approach is to have different Adapters for different views.