安卓ListView适配器OnClickListener问题

11
我创建了一个ListView,并为每个视图创建了自定义布局。在列表视图适配器中,我有几个TextView项目的onClickListeners。这些onClickListeners在列表视图适配器中工作,我可以获得视图的位置,但是当我尝试在onClickListeners中调用我的活动方法时,就会出现“无法对非静态方法进行静态引用”的错误提示。因此,我开始将所有东西转换为静态,这确实使事情按预期工作,但我相信大家都知道这是一个很大的错误,最终也会追上我。
到底该如何访问我的主活动中的方法而不使这些方法静态?我是新手,请原谅我这个问题。谢谢。
部分代码清单...
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;
}
1个回答

27

为什么不在您的活动中将onItemClickListener附加到ListView,而是要从ListView中的每个内部视图执行ItemClick?

        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);

在onItemClick方法中,您可以访问活动的方法。

编辑1: OnItemClickListener会给您以下参数:AdapterView parent、View view、int position和long。

您的TextView是view参数的子项,您可以使用类似childAt的方式访问它:

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
  }

}

编辑2:

在你的主活动中,记住,按照惯例所有类名都要大写,因此主类必须是Main类。

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);
}
}

现在,你的适配器

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;
}

希望它能够正常工作 :)


好的,我将值设置为示例,因为您已经获取了TextView实例,所以您可以随心所欲地使用它 :) - Franco
我已经纠结了一个小时,但还是无法确定自定义布局中的四个TextView中哪一个被点击了。我可以处理TextView,但仅此而已。胜利在望,哈哈。 - ReinD
ListView 是由 xml 布局构建而成的。更新了代码以包括 getView。 - ReinD
好的,我编辑了我的答案。当你调用这个方法时,你必须将你的“activity”实例转换为主类。如果你声明了你的方法为静态的,那么你必须在不实例化类的情况下访问它们(类方法),例如Main.assetInfo(...);所以,如果你没有声明你的方法为静态的,那么这些方法就是实例方法,你必须通过实例来访问它们。 - Franco
太棒了!哈哈,没错,这个有效。我猜这让你成为了已知宇宙中的乌伯程序员。你绝对得到了我的支持!非常感谢!^_^注意:在我研究的所有代码中,我从未见过使用这种技术。如果有问题出现,我会告诉你的。干杯! - ReinD
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接