11

I created a ListView with a custom layout for each view. I have several onClickListeners within the list view adapter for TextView items within the custom layout. The onClickListeners work within the list view adapter and I can obtain the position of the view, but when I try to make calls within the onClickListeners to methods in my activity, I get the "Cannot make a static reference to a non-static method" errors. So I started converting things to static, which made things work as intended, but I'm sure you all know it's a big mistake, which has finally caught up with me.

How the heck do I access methods in my main activity without making the methods static?? I'm new at this, so please forgive my noobish question. Thanks

partial code listing...

public class main extends Activity {
    private ArrayList<DataItem> dataItems;
    private DataItemAdapter aa;
    private ListView dataListView;  

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

        dataListView = (ListView)findViewById(R.id.dataListView);     
        dataItems = new ArrayList<DataItem>();
        int resID = R.layout.dataitem;
        aa = new DataItemAdapter(this, resID, dataItems);
        dataListView.setAdapter(aa);
        dataListView.setItemsCanFocus(true);

    populateArray();
}

public void populateArray() {
    DataItem newItem = new DataItem(
            "2008","Ferrari","F430","Red","ASX772"
        );
    dataItems.add(0, newItem);
    newItem = new DataItem(
            "2008","Ferrari","F430","Black","TZB123"
        );
    dataItems.add(0, newItem);
    newItem = new DataItem(
            "2009","Ferrari","F430","Red","MIDAS"
        );
    dataItems.add(0, newItem);      

    aa.notifyDataSetChanged();
}

public static void modelInfo(int pos) {
    Log.i("modelInfo", "=" + pos);
}

public static void makeInfo(int pos) {
    Log.i("makeInfo", "=" + pos);
}

public static void assetInfo(int pos) {
    Log.i("assetInfo", "=" + pos);
}

}


public class DataItemAdapter extends ArrayAdapter<DataItem> {
    private Activity activity;
    private int resource;
    private static LayoutInflater inflater=null;

    public DataItemAdapter(Activity _activity,int _resource,List<DataItem> _items) {
        super(_activity, _resource, _items);
        inflater = (LayoutInflater)_activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        resource = _resource;
        activity = _activity;
    }

public static class ViewHolder {
    TextView carYear;
    TextView carMake;
    TextView carModel;
    TextView carColor;
    TextView assetTag;
   }

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View vi=convertView;
    ViewHolder holder;
    if (convertView == null) {
        vi = inflater.inflate(resource, null);
        holder=new ViewHolder();
        holder.carYear = (TextView)vi.findViewById(R.id.carYear);
        holder.carMake = (TextView)vi.findViewById(R.id.carMake);
        holder.carModel = (TextView)vi.findViewById(R.id.carModel);
        holder.carColor = (TextView)vi.findViewById(R.id.carColor);
        holder.assetTag = (TextView)vi.findViewById(R.id.assetTag);
        vi.setTag(holder);
    } else {
        holder=(ViewHolder)vi.getTag();
    }

    DataItem item = getItem(position);  

    holder.carYear.setText(item.getCarYear());
    holder.carMake.setText(item.getCarMake());
    holder.carModel.setText(item.getCarModel());
    holder.carColor.setText(item.getCarColor());
    holder.assetTag.setText(item.getAssetTag());

    holder.carYear.setTag(position);
    holder.assetTag.setTag(position);

    final OnClickListener makeListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            LinearLayout ll = (LinearLayout)v.getParent();
            TextView tv = (TextView)ll.getChildAt(0);
            Integer pos = (Integer) tv.getTag();
            main.makeInfo(pos);
        }
    };
    holder.carMake.setOnClickListener(makeListener);

    final OnClickListener modelListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            LinearLayout ll = (LinearLayout)v.getParent();
            TextView tv = (TextView)ll.getChildAt(0);
            Integer pos = (Integer) tv.getTag();
            main.modelInfo(pos);

        }
   };        

    holder.carModel.setOnClickListener(modelListener);

    final OnClickListener assetListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            LinearLayout ll = (LinearLayout)v.getParent();
            TextView tv = (TextView)ll.getChildAt(0);
            Integer pos = (Integer) tv.getTag();
            main.assetInfo(pos);
        }
    };
    holder.assetTag.setOnClickListener(assetListener);        

    return vi;
}
DevfaR
  • 1,586
  • 1
  • 9
  • 19
ReinD
  • 123
  • 1
  • 1
  • 6

1 Answers1

27

why you dont attach an onItemClickListener to your ListView in your activity, instead of perform ItemClick from each inner view in the ListView

        dataListView = (ListView)findViewById(R.id.dataListView);     
        dataItems = new ArrayList<DataItem>();
        int resID = R.layout.dataitem;
        aa = new DataItemAdapter(this, resID, dataItems);
        dataListView.setAdapter(aa);
        //attach a listener to the list view
        dataListView.setOnItemClickListener (listener);

        dataListView.setItemsCanFocus(true);

and inside your listener on onItemClick method you can access the activity methods.

EDIT 1: the OnItemClickListener gives to you the following parameters, AdapterView parent, View view, int position, long

your individual TextView is a child of the view parameter and you can access to it getting the childAt... something like this:

OnItemClickListener listener = new OnItemClickListener (){

  @Override
  onItemClick(AdapterView<?> parent, View view, int position, long id){
      ((TextView)view.findViewById(R.id.yourTextViewId)).getText();
      //or do your stuff
  }

}

EDIT 2:

your main activity, remember, by convention all Class name are capitalized, so main class must be Main class

public class Main extends Activity {
    private ArrayList<DataItem> dataItems;
    private DataItemAdapter aa;
    private ListView dataListView;  

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

        dataListView = (ListView)findViewById(R.id.dataListView);     
        dataItems = new ArrayList<DataItem>();
        int resID = R.layout.dataitem;
        aa = new DataItemAdapter(this, resID, dataItems);
        dataListView.setAdapter(aa);
        dataListView.setItemsCanFocus(true);

    populateArray();
}

public void populateArray() {
    DataItem newItem = new DataItem(
            "2008","Ferrari","F430","Red","ASX772"
        );
    dataItems.add(0, newItem);
    newItem = new DataItem(
            "2008","Ferrari","F430","Black","TZB123"
        );
    dataItems.add(0, newItem);
    newItem = new DataItem(
            "2009","Ferrari","F430","Red","MIDAS"
        );
    dataItems.add(0, newItem);      

    aa.notifyDataSetChanged();
}

public void modelInfo(int pos) {
    Log.i("modelInfo", "=" + pos);
}

public void makeInfo(int pos) {
    Log.i("makeInfo", "=" + pos);
}

public void assetInfo(int pos) {
    Log.i("assetInfo", "=" + pos);
}
}

Now, your adapter

public class DataItemAdapter extends ArrayAdapter<DataItem> {
    private Activity activity;
    private int resource;
    private LayoutInflater inflater=null;

    public DataItemAdapter(Activity _activity,int _resource,List<DataItem> _items) {
        super(_activity, _resource, _items);
        inflater = (LayoutInflater)_activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        //i always do this way, but i dont think this is the error
        //inflater = LayoutInflater.from(_activity.getBaseContext());
        resource = _resource;
        activity = _activity;
    }

public static class ViewHolder {
    TextView carYear;
    TextView carMake;
    TextView carModel;
    TextView carColor;
    TextView assetTag;
   }

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View vi=convertView;
    ViewHolder holder;
    if (convertView == null) {
        vi = inflater.inflate(resource, null);
        holder=new ViewHolder();
        holder.carYear = (TextView)vi.findViewById(R.id.carYear);
        holder.carMake = (TextView)vi.findViewById(R.id.carMake);
        holder.carModel = (TextView)vi.findViewById(R.id.carModel);
        holder.carColor = (TextView)vi.findViewById(R.id.carColor);
        holder.assetTag = (TextView)vi.findViewById(R.id.assetTag);
        vi.setTag(holder);
    } else {
        holder=(ViewHolder)vi.getTag();
    }

    DataItem item = getItem(position);  

    holder.carYear.setText(item.getCarYear());
    holder.carMake.setText(item.getCarMake());
    holder.carModel.setText(item.getCarModel());
    holder.carColor.setText(item.getCarColor());
    holder.assetTag.setText(item.getAssetTag());

    holder.carYear.setTag(position);
    holder.assetTag.setTag(position);

    final OnClickListener makeListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            LinearLayout ll = (LinearLayout)v.getParent();
            TextView tv = (TextView)ll.getChildAt(0);
            Integer pos = (Integer) tv.getTag();
            //main.makeInfo(pos);
            ((Main)activity).makeInfo(pos);
        }
    };
    holder.carMake.setOnClickListener(makeListener);

    final OnClickListener modelListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            LinearLayout ll = (LinearLayout)v.getParent();
            TextView tv = (TextView)ll.getChildAt(0);
            Integer pos = (Integer) tv.getTag();
            //main.modelInfo(pos);
            ((Main)activity).modelInfo(pos);
        }
   };        

    holder.carModel.setOnClickListener(modelListener);

    final OnClickListener assetListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            LinearLayout ll = (LinearLayout)v.getParent();
            TextView tv = (TextView)ll.getChildAt(0);
            Integer pos = (Integer) tv.getTag();
            //main.assetInfo(pos);
            ((Main)activity).assetInfo(pos);
        }
    };
    holder.assetTag.setOnClickListener(assetListener);        

    return vi;
}

hope it works :)

Franco
  • 7,385
  • 3
  • 27
  • 22
  • Thanks for responding. Does onItemClickListener allow for indicating which of the individual TextView items was clicked within the custom layout VICE just referring to the individual view (position) that was clicked? How? That's probably the piece of information I'm missing. – ReinD Dec 16 '10 at 16:46
  • Thanks again. I understand your example, but I don't need the value of what was clicked, I need to know which TextView was clicked. i.e. TextView1, TextView2, TextView3, TextView4. I've been playing with it, but I don't know how to match the R.id.myTextViewId with what was clicked. – ReinD Dec 16 '10 at 19:21
  • ok, i put the value as example, since you get the TextView instance there, you can do what you want with it :) – Franco Dec 16 '10 at 19:25
  • I've been spinning my wheels for an hour and I still can't figure out how to determine which of the four TextViews within the custom layout have been clicked. I can do things with the TextViews, but that's about it. ftw lol – ReinD Dec 16 '10 at 21:23
  • do you constructs your ListView or inflates from a xml layout? you can figure out what is the TextView clicked by TextView id, TextView tag, TextView content, position in the adapter, etc. Maybe i dont understand your use case. maybe you can edit your post and put some extra data, like the getView method from your adapter :) – Franco Dec 16 '10 at 21:35
  • ListView is constructed from xml layout. Updated code to include getView – ReinD Dec 16 '10 at 23:49
  • oh, there is a very big difference, i dont imaginate that you put the four TextView in a single ListView item, just to make sure, can you post where and how do you set and implements (where you cannot call activity methods because static error) the onClickListener, i have a presumption but i'm not sure without that code requested – Franco Dec 17 '10 at 01:35
  • Updated code with onClickListeners and main activity methods. With the custom layout, you can put four TextViews into a single ListView. The above code works just fine because the main activty methods are now static. The problem is, which I alluded to initially, is that calling anything else in the main activity from the static methods requires those methods to become static as well. If you can figure out how to get around this problem is some way, then you are the uber coder of the known universe. ;-) – ReinD Dec 17 '10 at 03:13
  • BTW - There is a lot more to this code than is shown above - that's why I didn't initially show all the code. A lot of it has been stripped out to focus just on this particular problem. – ReinD Dec 17 '10 at 03:22
  • ok, i edited my answer, when you call this method you have to Cast your "activity" instance to Main Class, if you declared your methods static then you have to access them without instantiate the class (Class methods), ie Main.assetInfo(...); So, if you dont declare your method static then the methods are Instance methods and you have to access them through the instance – Franco Dec 17 '10 at 03:54
  • AMAZING!! LOL Yes, this works. I guess this makes you the Uber Coder of the Known Universe. You definitely get my vote! Thank you very much!! ^_^ Note: In all the code I've researched for this problem, I've never seen this technique used. I'll let you know if it comes back to bite me. Cheers – ReinD Dec 17 '10 at 04:15
  • my appologies, i didn't get with the problem until see the whole code, so, no problem man! cheers :) – Franco Dec 17 '10 at 04:17
  • I know its a long time ago you wrote this, but I've spend nearly 6 hours trying to work this out. so massive thank you to both of you! – Purplemonkey Apr 22 '12 at 12:56
  • @Franco plz look over this link http://stackoverflow.com/questions/12622028/onclick-button-is-not-working-in-listview#comment17038057_12622028 i am geting problem in onclick of button in Listview – Rao's Sep 28 '12 at 08:12