【问题标题】:Delete row from ListView created by Custom Adapter in onClickListener从 onClickListener 中的自定义适配器创建的 ListView 中删除行
【发布时间】:2015-03-16 05:32:57
【问题描述】:

您好,我从服务器获取数据并将它们传递到我的自定义适配器中以填充我的 ListView。以下是我的自定义适配器代码:

public class AppointmentAdapter extends BaseAdapter {

private AppointmentAdapter adapter;
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
HashMap<String, String> todo = new HashMap<String, String>();
 // String confirmation;
RelativeLayout confirm_corner;


public AppointmentAdapter(Activity a, ArrayList<HashMap<String,        String>> d) {
    activity = a;
    data=d;
    inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    //imageLoader=new ImageLoader(activity.getApplicationContext());
}

public int getCount() {
    return data.size();
}

public Object getItem(int position) {
    return position;
}

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



public View getView(final int position, View convertView, ViewGroup parent) {
    //View vi=convertView;
    //if(convertView==null)
       final View  vi = inflater.inflate(R.layout.appointments_list_item, null);
    adapter = new AppointmentAdapter(activity,data);
    TextView aid = (TextView)vi.findViewById(R.id.aid); // id
    TextView apptitle = (TextView)vi.findViewById(R.id.apptitle); // title
    TextView starts_date = (TextView)vi.findViewById(R.id.starts_date); // created_at
    TextView starts_time = (TextView)vi.findViewById(R.id.starts_time);
    TextView contact = (TextView)vi.findViewById(R.id.contact);
    TextView confirmation = (TextView)vi.findViewById(R.id.confirmation);
    confirm_corner = (RelativeLayout)vi.findViewById(R.id.confirm_corner);

    //CheckBox check = (CheckBox)vi.findViewById(R.id.tododone); // checkbox


    todo = data.get(position);

    // Setting all values in listview
    aid.setText(todo.get(AppointmentsFragment.TAG_AID));
    apptitle.setText(todo.get(AppointmentsFragment.TAG_APPTITLE));
    starts_date.setText(todo.get(AppointmentsFragment.TAG_STARTDATE));
    starts_time.setText(todo.get(AppointmentsFragment.TAG_STARTTIME));
    contact.setText(todo.get(AppointmentsFragment.TAG_CONTACT));
    confirmation.setText(todo.get(AppointmentsFragment.TAG_CONFIRMATION));
    String test = todo.get(AppointmentsFragment.TAG_USER_EMAIL);
    //Handle buttons and add onClickListeners
    ImageView accept = (ImageView)vi.findViewById(R.id.accept);
    ImageView deny = (ImageView)vi.findViewById(R.id.deny);
    //String test = confirmation.getText().toString();
    //&& (!test.equals(MainActivity.user_email))
    Log.d("CONFIRMATION: ", MainActivity.user_email);
    if (confirmation.getText().toString().equals("pending")  ){
        Log.d("PASS CONFIRMATION: ", confirmation.getText().toString());
        confirm_corner.setVisibility(View.VISIBLE);
    }

    accept.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v) { 
            //do something
            confirm_corner = (RelativeLayout)vi.findViewById(R.id.confirm_corner);
            Log.d("Button accept: ", MainActivity.user_email);
            new Confirm_appointment().execute();
            //vi.setBackgroundColor(Color.RED);
            confirm_corner.setVisibility(View.GONE);


        }
    });
    deny.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v) { 
            //do something
            Log.d("Button deny: ", MainActivity.user_email);
            new Deny_appointment().execute();
            confirm_corner.setVisibility(View.INVISIBLE);
            //adapter = new AppointmentAdapter(this,data);
            data.remove(position);
            data.clear();
            data.addAll(data); 
            adapter.notifyDataSetChanged();
        }
    });


    return vi;
}

我希望当我单击拒绝按钮时要删除该行。我应该在我的代码中更改什么来解决这个问题?

【问题讨论】:

    标签: android listview android-listview arraylist android-custom-view


    【解决方案1】:

    不要在AppointmentAdapter 内创建新的AppointmentAdapter。当您在删除一行后尝试notifyDataSetChanged() 时,您会通知错误的适配器。您通知新构建的适配器,它不是已更改数据的适配器。 (新构建的也没有附加到列表视图,所以他们无法确保通知到达那里。)

    您应该记住,只需一个适配器即可与具有多个项目视图的 ListView 一起工作。您为每个项目视图构建一个适配器,但这不起作用。适配器应该与 ListView 合作,而不是与项目视图合作。

    我会用你的代码做很多不同的事情,我认为你应该实现 View Holder 模式。你可以阅读它here

    更新

    您必须在this 上调用它,而不是调用adapter.notifyDataSetChanged()this 应该是您刚刚删除该行的适配器。因为您正在为View.OnClickListener 使用匿名(非静态)内部类,所以您可以使用AppointmentAdapter.this 来访问外部类,这是您想要的适配器。

    试试这个:

    deny.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v) { 
            //do something
            Log.d("Button deny: ", MainActivity.user_email);
            new Deny_appointment().execute();
            confirm_corner.setVisibility(View.INVISIBLE);
            AppointmentAdapter.this.data.remove(position);
            AppointmentAdapter.this.notifyDataSetChanged();
        }
    });
    

    顺便说一句,我同意 Willis 的观点,即清除数据并重新加载数据的行似乎是错误的。所以我也把它们扔了。

    【讨论】:

    • 当我删除新的 AppointmentAdapter 时,我在 adapter.notifyDataSetChanged() 中得到一个 NullExceptionError 。能否请您粘贴一些您认为可行的代码
    • 那是因为现在adapter 从未被分配,因此保持为空。你根本不需要那个变量,也删除private AppointmentAdapter adapter; 行。查看我更新的答案以获得更多帮助。
    【解决方案2】:

    以下两个调用的目的是什么?:

    data.clear();
    data.addAll(data); 
    

    要从ListView 中删除元素,只需调用data.remove(position),然后更新Adapter (adapter.notifyDataSetChanged())。看看这是否有效。

    【讨论】:

    • 当我使用你的方法时,它不会自动更新用户界面。我必须滑动包含片段的选项卡,当我返回时,该行就消失了。它不应该自动执行吗?
    • 为什么onClickListener 在你的Adapter getView 方法中?您应该将侦听器放在您的 Fragment 中并从那里删除行。
    • 我看到了很多在getView中使用onClickListener的例子,当它是每一行的按钮时。
    • 哦,好吧,我误解了应用程序。 ListView 中的每一行都有一个拒绝和接受 Button,而不是整个 UI 中只有两个 Buttons?
    • 如果我在 Fragment 中使用 Listeners,我应该如何获取单击按钮的行的位置?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 2019-05-23
    • 1970-01-01
    相关资源
    最近更新 更多