我正在尝试创建一个列表视图,该列表视图由其中具有多个可点击布局的项目填充。在这种情况下,列表视图是联系人列表。列表视图中的每一行代表一个单独的联系人,列表视图项上的每个按钮都应该触发与该联系人相关的操作 - 例如,查看和预约。
每个列表视图项的 XML:
<LinearLayout
android:id="@+id/layoutBookAppt"
android:layout_width="56dp"
android:layout_height="fill_parent"
android:layout_alignBottom="@+id/divider"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:gravity="center_horizontal|center_vertical"
android:orientation="vertical"
android:background="@drawable/list_selector_flatcolour"
android:onClick="newAppt" >
<ImageView
android:id="@+id/apptNew"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@drawable/appt_new" />
</LinearLayout>
<RelativeLayout
android:id="@+id/layoutInfo"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:padding="8dp"
android:layout_toStartOf="@id/layoutBookAppt"
android:layout_toLeftOf="@id/layoutBookAppt"
android:onClick="viewCustomer"
android:background="@drawable/list_selector_flatcolour" >
<!-- Various contact information here, name, number etc -->
</RelativeLayout>
我的适配器:
public class CustListAdapter extends BaseAdapter {
ArrayList<Customer> customers;
Context ctx;
public CustListAdapter(Context context, ArrayList<Customer> custs) {
this.ctx = context;
this.customers = custs;
}
static class ViewHolder {
RelativeLayout info;
LinearLayout book;
TextView name;
TextView number;
int pos; // Not sure if this is the best approach
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final Customer customer = getItem(position);
ViewHolder viewHolder;
if (convertView == null) { //inflate convertView and populate viewHolder
viewHolder = new ViewHolder();
viewHolder.pos = position;
convertView = LayoutInflater.from(ctx).inflate(R.layout.customer_info, parent, false);
viewHolder.info = (RelativeLayout) convertView.findViewById(R.id.layoutInfo);
viewHolder.book = (LinearLayout) convertView.findViewById(R.id.layoutBookAppt);
viewHolder.name = (TextView) convertView.findViewById(R.id.lblCustName);
viewHolder.number = (TextView) convertView.findViewById(R.id.lblNumber);
convertView.setTag(viewHolder);
}
else
viewHolder = (ViewHolder) convertView.getTag();
// set the textviews here
return convertView;
}
/* Other mandatory functions here */
}
最后,我活动的相关部分:
public class CustListActivity extends Activity {
ListView lstCustomers;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cust_list);
// Show the Up button in the action bar.
setupActionBar();
lstCustomers = (ListView) findViewById(R.id.custlist);
populateListView();
}
private void populateListView() {
// Populate arraylist 'customers' with cursor from database
lstCustomers.setAdapter(new CustListAdapter(this, customers));
}
public void newAppt(View view)
{
if (view == null)
Gen.popup("View is null");
else
{
ViewHolder vh = (ViewHolder)view.getTag();
Gen.popup("book " + String.valueOf(vh.pos));
}
}
public void viewCustomer(View view)
{
if (view == null)
Gen.popup("View is null");
else
{
ViewHolder vh = (ViewHolder)view.getTag();
Gen.popup("view " + String.valueOf(vh.pos));
}
}
}
logcat 中的异常:
09-26 09:37:38.070: E/AndroidRuntime(766): FATAL EXCEPTION: main
09-26 09:37:38.070: E/AndroidRuntime(766): java.lang.IllegalStateException: Could not execute method of the activity
09-26 09:37:38.070: E/AndroidRuntime(766): at android.view.View$1.onClick(View.java:3704)
09-26 09:37:38.070: E/AndroidRuntime(766): at android.view.View.performClick(View.java:4232)
09-26 09:37:38.070: E/AndroidRuntime(766): at android.view.View$PerformClick.run(View.java:17298)
09-26 09:37:38.070: E/AndroidRuntime(766): at android.os.Handler.handleCallback(Handler.java:615)
09-26 09:37:38.070: E/AndroidRuntime(766): at android.os.Handler.dispatchMessage(Handler.java:92)
09-26 09:37:38.070: E/AndroidRuntime(766): at android.os.Looper.loop(Looper.java:137)
09-26 09:37:38.070: E/AndroidRuntime(766): at android.app.ActivityThread.main(ActivityThread.java:4921)
09-26 09:37:38.070: E/AndroidRuntime(766): at java.lang.reflect.Method.invokeNative(Native Method)
09-26 09:37:38.070: E/AndroidRuntime(766): at java.lang.reflect.Method.invoke(Method.java:511)
09-26 09:37:38.070: E/AndroidRuntime(766): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
09-26 09:37:38.070: E/AndroidRuntime(766): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
09-26 09:37:38.070: E/AndroidRuntime(766): at dalvik.system.NativeStart.main(Native Method)
09-26 09:37:38.070: E/AndroidRuntime(766): Caused by: java.lang.reflect.InvocationTargetException
09-26 09:37:38.070: E/AndroidRuntime(766): at java.lang.reflect.Method.invokeNative(Native Method)
09-26 09:37:38.070: E/AndroidRuntime(766): at java.lang.reflect.Method.invoke(Method.java:511)
09-26 09:37:38.070: E/AndroidRuntime(766): at android.view.View$1.onClick(View.java:3699)
09-26 09:37:38.070: E/AndroidRuntime(766): ... 11 more
09-26 09:37:38.070: E/AndroidRuntime(766): Caused by: java.lang.NullPointerException
09-26 09:37:38.070: E/AndroidRuntime(766): at com.example.myapp.CustListActivity.newAppt(CustListActivity.java:110)
09-26 09:37:38.070: E/AndroidRuntime(766): ... 14 more
所以基本上我想要做的是能够在用户按下列表视图项时获得两位信息。
- 行位置
- 按下的布局
我可以分别获得这些细节,但事实证明两者都很难。我可以通过 XML 触发单独的 onClick 事件,但无法弄清楚如何找出被按下的行的位置。我也可以通过设置onItemClickListener
,但这仅在按下列表项本身时触发,而不是其中的任何视图。
使用我的newAppt()
和viewCustomer()
函数,我正在尝试使用getTag()
(我不确定这是否是最好的方法,但我正在尝试任何方法)来获取行位置 - 但是getTag()
总是会返回 null,这让我完全不知所措。
我在正确的轨道上吗?如果不是,那么是同时获得被按下的行和视图的最佳方式吗?
(编辑:Gen.popup
是我自己的 TOAST 速记方法)。