【问题标题】:ListView with Buttons and static String Array带有按钮和静态字符串数组的 ListView
【发布时间】:2015-02-13 09:43:34
【问题描述】:

我想创建一个ListView,其中每个row 都有两个按钮。 Button1Button2

我已经阅读了一些关于如何创建 CustomAdapter 或扩展 BaseAdapter 的教程,但没有一个对我有用,这就是我在这里提出一个新问题的原因。

我的strings.xml 中有一个静态(不变的)字符串数组:

 <string-array name="locations_array">
   <item>Item1</item>
   <item>Item2</item>
 </string-array>

我想在我的 ListView 中使用这个 Array(我设法创建一个带有 onClick 事件的普通 ListView,但现在我想为每一行添加按钮)并向每一行添加两个按钮,每个按钮都有自己的 onClick 事件.

我已经按照this answers here 和网上其他一些教程的步骤进行操作,但在尝试setText 时,我总是得到NullPointerException

CustomAdapter.java

public class CustomAdapter extends BaseAdapter implements ListAdapter {
    private ArrayList<String> list = new ArrayList<>();
    private Context ctx;

    public CustomAdapter(ArrayList<String> list, Context ctx){
        this.list = list;
        this.ctx = ctx;
    }

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

    @Override
    public Object getItem(int position) {
        Log.d("TAG", list.get(position));
        return list.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        if(view == null){
            LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.layout_listview,null);
        }
        Log.d("TAG", list.get(position));
        TextView listItemText = (TextView) view.findViewById(R.id.list_item_string);
        listItemText.setText(list.get(position));

        Button localData = (Button) view.findViewById(R.id.button1);
        Button onlineData = (Button) view.findViewById(R.id.button2);

        localData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        onlineData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        return view;
    }
}

我在 Fragment 中使用了适配器:

locationsArray = getResources().getStringArray(R.array.locations_array);
ArrayList<String> data = new ArrayList<>(Arrays.asList(locationsArray));
CustomAdapter adapter = new CustomAdapter(data,getActivity());
listView.setAdapter(adapter);

但这不起作用。所有教程都专注于我需要的其他内容。我只需要在每行上放置两个按钮,并使用现有的字符串数组。我不想动态添加任何东西等。只需使用我已经创建的字符串数组。

编辑(添加我忘记的 XML 文件!)

R.layout.layout_listview(EditText是用来过滤List的):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <EditText
        android:id="@+id/et_filter"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:hint="Search Location">
    </EditText>
    <ListView
        android:id="@+id/list"
        android:layout_height="wrap_content"
        android:layout_width="match_parent">
    </ListView>


</LinearLayout>

R.layout.layout_listview_buttons:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/list_item_string"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"
        android:paddingLeft="8dp"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/button1"
        android:layout_width="80dp"
        android:layout_height="40dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:text="Online Data"

        android:textColor="#0099CC" />

    <Button
        android:id="@+id/button2"
        android:layout_width="80dp"
        android:layout_height="40dp"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/button1"
        android:layout_marginTop="3dp"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:text="Local Data"
        android:textColor="#0099CC" />



</RelativeLayout>

LogCat 异常:

12-15 11:24:10.852  14626-14626/com.inodroid.myweatherapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.inodroid.myweatherapp, PID: 14626
    java.lang.NullPointerException
            at com.inodroid.myweatherapp.Data.CustomAdapter.getView(CustomAdapter.java:59)

代码行:

listItemText.setText(list.get(position));

希望有人可以帮助我。

干杯

【问题讨论】:

  • 请粘贴您的 R.layout.layout_listview 文件 :-)
  • @Kelevandos 啊,抱歉,不知道我是怎么忘记添加 XML 文件的。我把它们都放了!
  • 我认为堆栈跟踪也会很有用
  • 我认为您在适配器中膨胀了错误的 xml 文件。将view = inflater.inflate(R.layout.layout_listview,null); 更改为view = inflater.inflate(R.layout.layout_listview_buttons,null);
  • 就是这样! Oh-My-God..so embarrassing,非常感谢你们!!

标签: java android listview android-listview


【解决方案1】:

请尝试以下方法:

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<ListView
    android:id="@+id/lvItems"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</ListView>

</LinearLayout>

MainActivity.java:

public class MainActivity extends Activity {

private ListView lvItems;

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

    lvItems = (ListView) findViewById(R.id.lvItems);
    String[] locationsArray = getResources().getStringArray(
            R.array.locations_array);
    CustomAdapter adapter = new CustomAdapter(this, locationsArray);
    lvItems.setAdapter(adapter);

lvItems.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            ViewHolder holder = (ViewHolder) view.getTag();
            String item = holder.getItem();
            // Do what ever with your Item.
            // If You need the position, you can take it from above
            // position.
        }
    });
}

}

list_item.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="wrap_content"
android:orientation="vertical"
android:padding="5dp" >

<Button
    android:id="@+id/btnLocalData"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="local Data" />

<TextView
    android:id="@+id/tvItem"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/btnLocalData"
    android:layout_alignTop="@+id/btnOnlineData"
    android:layout_toLeftOf="@+id/btnOnlineData"
    android:layout_toRightOf="@+id/btnLocalData"
    android:gravity="center"
    android:text="Item"
    android:textSize="16dp"
    android:textStyle="bold" />

<Button
    android:id="@+id/btnOnlineData"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:text="Online Data" />

</RelativeLayout>

CustomAdapter.java:

public class CustomAdapter extends ArrayAdapter<String> {

private LayoutInflater lf;

public CustomAdapter(Context context, String[] objects) {
    super(context, 0, objects);
    lf = LayoutInflater.from(context);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    if (convertView == null) {
        convertView = lf.inflate(R.layout.list_item, parent, false);
        holder = new ViewHolder();
        holder.btnLocalData = (Button) convertView
                .findViewById(R.id.btnLocalData);
        holder.btnOnlineData = (Button) convertView
                .findViewById(R.id.btnOnlineData);
        holder.tvItem = (TextView) convertView.findViewById(R.id.tvItem);
        holder.initListeners();
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.setData(getItem(position));

    return convertView;
}

public static class ViewHolder {
    TextView tvItem;
    Button btnOnlineData;
    Button btnLocalData;
    String mItem;

    public String getItem(){
        return mItem;
    }

    public void setData(String item) {
        mItem = item;
        tvItem.setText(item);
    }

    public void initListeners() {
        btnLocalData.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(),
                        "Local Data Clicked : " + mItem, Toast.LENGTH_LONG)
                        .show();
            }
        });
        btnOnlineData.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(),
                        "Online Data Clicked : " + mItem, Toast.LENGTH_LONG)
                        .show();
            }
        });
    }

}

}

【讨论】:

  • 这是一个很好的答案! :) 但现在我遇到了问题,ListView 项目的 onItemClick 不起作用。只有按钮点击有效。但我也希望 ListView 中的项目是可点击的并且有自己的 onItemClickListeners,我应该如何使用我的自定义适配器来实现呢?
  • 嘿,又是我。你现在可能吗,我怎样才能在单击按钮的同一行中获取 ListView Item 的位置?例如。当我单击按钮时,我想存储 ListView 项的文本,即与单击的按钮在同一行中。
【解决方案2】:

请使用 ViewHolder 模式。您将需要这些:

item_listrow.xml:

<LinearLayout
android:layout_height = "match_parent";
andorid:layout_width  = "match_parent";
andorid:orientation   = "horizontal";
>

<Button
android:id = "@+id/button1"
android:layout_height = "match_parent";
andorid:layout_width  = "0dp";
andorid:layout_weight = 1;
/>

<Button
android:id = "@+id/button2"
android:layout_height = "match_parent";
andorid:layout_width  = "0dp";
andorid:layout_weight = 1;
/>

</LinaerLayout>

您的 Adapter getView() 方法应该如下所示:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view = convertView;
    if(view == null){
        LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.layout_listrow,null);
        Holder h = new Holder();
        h.button1 = (Button) view.findViewById(R.id.button1);
        h.button2 = (Button) view.findViewById(R.id.button2);
        view.setTag(h);      
    }

    Holder holder = (Holder) view.getTag();

    holder.button1.setText(list.get(0));
    holder.button2.setText(list.get(1));
    listItemText.setText(list.get(position));

    holder.button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

        }
    });

    holder.button2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

        }
    });

    return view;
}

上面用到的Holder类:(只是嵌套在Adapter类里面)

public static class Holder {
    Button button1;
    Button button2;
}

这是基于给定方法isDeveloperMode()隐藏按钮的代码:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view = convertView;
    if(view == null){
        LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.layout_listrow,null);
        Holder h = new Holder();
        h.button1 = (Button) view.findViewById(R.id.button1);
        h.button2 = (Button) view.findViewById(R.id.button2);
        view.setTag(h);      
    }

    Holder holder = (Holder) view.getTag();

    if(isDeveloperMode()){
        holder.button1.setVisibility(View.VISIBLE);
        holder.button2.setVisibility(View.VISIBLE);
        holder.button1.setText(list.get(0));
        holder.button2.setText(list.get(1));
        listItemText.setText(list.get(position));

        holder.button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        holder.button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
    } else {
        holder.button1.setVisibility(View.GONE);
        holder.button2.setVisibility(View.GONE); 
    }

    return view;
}

【讨论】:

  • 代码是手工输入的,如有任何错误或错别字请见谅;-)
  • 我在声明按钮的地方添加了 XML。但我没有使用 Holder 类,我会尝试添加它。但是,我在setText(list.get(position) 上收到 LogCat 错误“NullPointerException”
  • 这确实有效,但是 onClickListeners nwo 不起作用,他们不识别“button1”和“button2”..我应该添加 holder.button1 吗?
  • 确实,错了,它必须是holder.button1holder.button2(更正答案)
  • 感谢您的帮助!我现在想知道为什么我的 ItemClickListener 在我的 ListView 中不起作用?当我从 ListView 单击 Iem 时,它什么也不做。没有错误。但它应该将所选项目存储到变量中,但现在它什么也不做。
【解决方案3】:

在适配器中将代码更改为以下

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if(convertView== null){
        LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView= inflater.inflate(R.layout.layout_listview,null);
    }
    Log.d("TAG", list.get(position));
    TextView listItemText = (TextView) convertView.findViewById(R.id.list_item_string);
    listItemText.setText(list.get(position));

    Button localData = (Button) convertView.findViewById(R.id.button1);
    Button onlineData = (Button) convertView.findViewById(R.id.button2);

    localData.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

        }
    });

    onlineData.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

        }
    });

    return convertView;
}

【讨论】:

    【解决方案4】:

    尝试代替

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {    
                View view = convertView;
                if(view == null){
                    LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    view = inflater.inflate(R.layout.layout_listview,null);
                }
                Log.d("TAG", list.get(position));
                TextView listItemText = (TextView) view.findViewById(R.id.list_item_string);
    

    使用

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
                View view = super.getView(position, convertView, parent);       
                Log.d("TAG", list.get(position));
                TextView listItemText = (TextView) view.findViewById(R.id.list_item_string);
    

    【讨论】:

      猜你喜欢
      • 2013-04-14
      • 1970-01-01
      • 2018-08-07
      • 1970-01-01
      • 1970-01-01
      • 2019-02-23
      • 2012-11-20
      • 2011-01-23
      • 1970-01-01
      相关资源
      最近更新 更多