我有ListView
,如下图所示
每个白框都是一个单独的ListView
行。每个ListView
行的右上角都有一个Button
。
我正在尝试在每行OnClickListener
上设置Button
。只要单击此Button
,我就想删除该行。
每个ListView
行中的数据来自Firebase
数据库。因此,只要在Button
的任意行中点击了交叉ListView
,我就会获得Timestamp
的值,然后将此Timestamp
作为参数传递到单独的搜索方法中在此Timestamp
的数据库中。 <{1}}数据库中以Firebase
为其子项的任何键都将被删除。
用于删除Timestamp
行数据的方法工作正常,因为它删除了与此方法中传递的ListView
相关联的数据作为参数。
问题是,当点击任何Timestamp
上的按钮时,我得到的Timestamp
值是错误的。例如,在上图中,如果我点击ListView
ListView
Timestamp
行的第27-01-2018 05-31-22AM
行,而不是Timestamp
,我会获得Timestamp
ListView
的最后一行,因此删除了错误的数据。
以下是相关代码:
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
行?
答案 0 :(得分:1)
尝试对CustomOutboxListAdapter
课程进行这些更改。
在CustomOutboxListAdapter
中未执行View.OnClickListener
。从:
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;
。
对于getItemId(int i)
实施,我认为应该是这样的:
@Override
public long getItemId( int position ) {
return this.sentMsgsList.get(position).getId();
}
然后在SentMessageTemplate
类中,它应该实现:
public int getId() {
// return unique ID for object
....
}
答案 1 :(得分:0)
错误是只有当适配器为 > react-app-rewired build
sh: 1: react-app-rewired: not found
npm ERR! file sh
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn
npm ERR! client@0.1.0 build: `react-app-rewired build`
npm ERR! spawn ENOENT
npm ERR!
npm ERR! Failed at the client@0.1.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /app/.npm/_logs/2018-01-27T03_26_58_947Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! infinity2o_server@1.0.0 heroku-postbuild: `NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the infinity2o_server@1.0.0 heroku-postbuild script.
创建新视图时才调用btnDeleteMsg.setOnClickListener(this);
。它仅在应用程序启动时发生,在ListView重用视图之后并且不调用ListView
。因此,要解决您的问题,请将此行移至btnDeleteMsg.setOnClickListener(this);
如下所示
holder.receiverUsernameText.setText(stu.getMsgReceiver());
答案 2 :(得分:0)
我不确定我完全理解这个问题但是:
您可以通过在视图上调用setId来设置ID。为您的行提供唯一的数字。然后使用onClick函数中的getId检索ID,以了解单击了哪一行,以便删除它。这比使用Timestamp更好,因为它们可能巧合地重叠,而你可以确保ID都是不同的。