问题描述
我有ListView
,如下图所示
每个白框是一个单独的ListView
行.每个ListView
行在右上角都有一个Button
.
each white box is a separate ListView
row. Each ListView
row has a Button
at top right corner.
我正在尝试在每一行的Button
上设置一个OnClickListener
.每当单击此Button
时,我都想删除该行.
I am trying to set a OnClickListener
on Button
of each row. Whenever this Button
is clicked, i want to delete that row.
每个ListView
行中的数据都来自Firebase
数据库.因此,每当在ListView
的任何行中单击十字Button
时,我都会得到Timestamp
的值,然后将此Timestamp
作为参数传递给在数据库中搜索此Timestamp
的单独方法中. Firebase
数据库中具有此Timestamp
作为其子级的所有键都将被删除.
The data in each ListView
row is coming from Firebase
database. So whenever the cross Button
is clicked on in any row of ListView
, i get the value of Timestamp
and then pass this Timestamp
as an argument in a separate method that searches in the database for this Timestamp
. Any key in the Firebase
database that has this Timestamp
as its child is deleted.
用于删除ListView
行数据的方法可以正常工作,因为它删除与此方法中作为参数传递的Timestamp
关联的数据.
Method that is used to delete the ListView
row data is working fine as it deletes the data associated with the Timestamp
passed in this method as an argument.
问题是单击任何ListView
上的按钮时得到的Timestamp
值是错误的.例如,在上图中,如果我单击带有27-01-2018 05-31-22AM
的Timestamp
的第二个ListView
行,而不是获取此Timestamp
,而是获取了ListView
最后一行的Timestamp
,因此错误的数据将被删除.
Problem is that the Timestamp
value that i am getting when a button is clicked on any ListView
is wrong. For example, in the image above, if i click on 2nd ListView
row with Timestamp
of 27-01-2018 05-31-22AM
, instead of getting this Timestamp
, i get the Timestamp
of the last row of ListView
and consequently wrong data is deleted.
这是相关代码:
onClick()方法
@Override
public void onClick(View view) {
//get the parent view i.e. listview row on which delete button is clicked
ConstraintLayout listviewRow = (ConstraintLayout) btnDeleteMsg.getParent();
//get the textview containing receiver username from the view on which delete button is clicked
TextView textviewReceiver = listviewRow.findViewById(R.id.outbox_msgReceiverUsername);
//get the textview containing timestamp value from the view on which delete button is clicked
TextView textTimestamp = listviewRow.findViewById(R.id.outbox_msgSentTime);
//get the values of message receiver username and timestamp
//timestamp value will be used to determine which message to delete
//from database
String receiverUsername = textviewReceiver.getText().toString();
String timestamp = textTimestamp.getText().toString();
//call delSentMsg() method in SentMessages Fragment using SentMessages Fragment
//instance passed in the constructor of this class
sentMsgsFragment.deleteSentMsg(receiverUsername, timestamp);
}
ListView行布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="15dp"
android:background="#fff">
<Button
android:id="@+id/btn_deleteMsg_SMF"
android:layout_width="17dp"
android:layout_height="17dp"
android:background="@drawable/cross_image"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:id="@+id/outbox_msgText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#000"
android:textSize="22sp"
android:paddingTop="10dp"
app:layout_constraintTop_toBottomOf="@id/btn_deleteMsg_SMF"/>
<TextView
android:id="@+id/outbox_msgReceiverLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/to_text_label"
android:textColor="#000"
android:textSize="18sp"
app:layout_constraintTop_toBottomOf="@id/outbox_msgText"
app:layout_constraintLeft_toLeftOf="parent"
android:paddingTop="10dp"/>
<TextView
android:id="@+id/outbox_msgReceiverUsername"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
app:layout_constraintLeft_toRightOf="@id/outbox_msgReceiverLabel"
android:layout_marginLeft="10dp"
app:layout_constraintTop_toBottomOf="@id/outbox_msgText"
android:paddingTop="10dp"/>
<TextView
android:id="@+id/outbox_msgDateLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sent_on_label"
android:textColor="#000"
android:textSize="18sp"
app:layout_constraintTop_toBottomOf="@id/outbox_msgReceiverLabel"
app:layout_constraintLeft_toLeftOf="parent"
android:paddingTop="10dp"/>
<TextView
android:id="@+id/outbox_msgSentTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
app:layout_constraintLeft_toRightOf="@id/outbox_msgDateLabel"
app:layout_constraintTop_toBottomOf="@id/outbox_msgReceiverLabel"
android:layout_marginLeft="10dp"
app:layout_constraintBaseline_toBaselineOf="@id/outbox_msgDateLabel"
android:paddingTop="10dp"/>
</android.support.constraint.ConstraintLayout>
ListView适配器类
public class CustomOutboxListAdapter extends BaseAdapter implements View.OnClickListener{
private ArrayList<SentMessageTemplate> sentMsgsList;
private Context context;
private Button btnDeleteMsg;
private SentMessages sentMsgsFragment;
public CustomOutboxListAdapter(ArrayList<SentMessageTemplate> list, Context cont, SentMessages sm){
this.sentMsgsList = list;
this.context = cont;
this.sentMsgsFragment = sm;
}
@Override
public int getCount() {
return this.sentMsgsList.size();
}
@Override
public Object getItem(int position) {
return this.sentMsgsList.get(position);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
LayoutInflater inf = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inf.inflate(R.layout.listview_outbox_messages_row, null);
//private inner class used to minimize the calls to "findViewById" method
holder = new ViewHolder();
holder.datetimeText = convertView.findViewById(R.id.outbox_msgSentTime);
holder.messageText = convertView.findViewById(R.id.outbox_msgText);
holder.receiverUsernameText = convertView.findViewById(R.id.outbox_msgReceiverUsername);
convertView.setTag(holder);
//click listener for delete button
btnDeleteMsg = convertView.findViewById(R.id.btn_deleteMsg_SMF);
btnDeleteMsg.setOnClickListener(this);
}
else {
holder = (ViewHolder)convertView.getTag();
}
SentMessageTemplate stu = sentMsgsList.get(position);
holder.datetimeText.setText(stu.getTimestamp());
holder.messageText.setText(stu.getMessageContent());
holder.receiverUsernameText.setText(stu.getMsgReceiver());
return convertView;
}
@Override
public void onClick(View view) {
//get the parent view i.e. listview row on which delete button is clicked
ConstraintLayout listviewRow = (ConstraintLayout) btnDeleteMsg.getParent();
//get the textview containing receiver username from the view on which delete button is clicked
TextView textviewReceiver = listviewRow.findViewById(R.id.outbox_msgReceiverUsername);
//get the textview containing timestamp value from the view on which delete button is clicked
TextView textTimestamp = listviewRow.findViewById(R.id.outbox_msgSentTime);
//get the values of message receiver username and timestamp
//timestamp value will be used to determine which message to delete
//from database
String receiverUsername = textviewReceiver.getText().toString();
String timestamp = textTimestamp.getText().toString();
//call delSentMsg() method in SentMessages Fragment using SentMessages Fragment
//instance passed in the constructor of this class
sentMsgsFragment.deleteSentMsg(receiverUsername, timestamp);
}
private static class ViewHolder{
public TextView datetimeText;
public TextView messageText;
public TextView receiverUsernameText;
}
}
问题
我认为问题是我无法正确获得单击交叉按钮的ListView
行.单击按钮时如何确定ListView
的行?
Question
I think the problem is that i am not able to correctly get the ListView
row on which cross button is clicked on. How can i determine the row of ListView
when a button is clicked on?
推荐答案
尝试对CustomOutboxListAdapter
类进行这些更改.
Try making these changes to CustomOutboxListAdapter
class.
在CustomOutboxListAdapter
中不要实现View.OnClickListener
.将其类声明从以下位置更改:
In CustomOutboxListAdapter
don't implement View.OnClickListener
. Change it's class declaration from:
public class CustomOutboxListAdapter extends BaseAdapter implements View.OnClickListener{
收件人:
public class CustomOutboxListAdapter extends BaseAdapter {
并删除其中的onClick
方法:
@Override
public void onClick(View view) {
将public View getView(int position, View convertView, ViewGroup parent)
替换为:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
LayoutInflater inf = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inf.inflate(R.layout.listview_outbox_messages_row, null);
//private inner class used to minimize the calls to "findViewById" method
holder = new ViewHolder();
holder.datetimeText = convertView.findViewById(R.id.outbox_msgSentTime);
holder.messageText = convertView.findViewById(R.id.outbox_msgText);
holder.receiverUsernameText = convertView.findViewById(R.id.outbox_msgReceiverUsername);
convertView.setTag(holder);
}
else {
holder = (ViewHolder)convertView.getTag();
}
SentMessageTemplate stu = sentMsgsList.get(position);
holder.datetimeText.setText(stu.getTimestamp());
holder.messageText.setText(stu.getMessageContent());
holder.receiverUsernameText.setText(stu.getMsgReceiver());
// use local variable so it is always referenced correctly
Button deleteBtn = convertView.findViewById(R.id.btn_deleteMsg_SMF);
// Cache row position inside the button using `setTag`
deleteBtn.setTag(position);
// Attach the click event handler
deleteBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = (Integer) view.getTag();
// Access the row position here to get the correct data item
SentMessageTemplate sentMessageTemplate = getItem(position);
String receiverUsername = sentMessageTemplate.getTimestamp();
String timestamp = sentMessageTemplate.getMsgReceiver();
sentMsgsFragment.deleteSentMsg(receiverUsername, timestamp);
}
});
return convertView;
}
只需删除不再使用的成员变量private Button btnDeleteMsg;
.
Just delete the member variable private Button btnDeleteMsg;
as not used anymore.
同样对于getItemId(int i)
实施,我认为应该是这样的:
Also for getItemId(int i)
implementation, I think it should be something like:
@Override
public long getItemId( int position ) {
return this.sentMsgsList.get(position).getId();
}
然后在SentMessageTemplate
类中,它应该实现:
Then in SentMessageTemplate
class, it should implement:
public int getId() {
// return unique ID for object
....
}
这篇关于在Listview行布局中的按钮上设置单击侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!