android - 具有设置可见性的 Recyclerview
问题描述
我的管理应用程序有一个费用请求。我想要实现的是当用户单击批准按钮时,其上的文本应更改为已批准,拒绝按钮应消失,反之亦然。我无法做到这一点,我已经尝试了一切,但每次尝试解决这个问题时都会得到更奇怪的输出。请附上您更改的原因,因为它会对我有所帮助。谢谢
这是我的代码
package com.emlocks.timeaccess;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class Expenses extends AppCompatActivity {
NetworkController networkController;
Bundle ss;
private SharedPreferences prefs;
List<ExpenseP> expensep = new ArrayList<>();
RecyclerView rvRegs;
Gson gson = new Gson();
HashMap<Integer, String> hmap = new HashMap<>();
public static final String TAG = "Expenses";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_expenses);
ss = savedInstanceState;
networkController = RetrofitClientInstance.getRetrofitInstance().create(NetworkController.class);
prefs = getSharedPreferences(getResources().getString(R.string.prefs), MODE_PRIVATE);
rvRegs = findViewById(R.id.rvExpense);
networkController = RetrofitClientInstance.getRetrofitInstance().create(NetworkController.class);
networkController.getexpense("Bearer " + prefs.getString("token", null), prefs.getString("email", null)).enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (response.code() == 200) {
JsonArray array = response.body().getAsJsonArray("data");
System.out.println(array);
Log.d(TAG, "onResponse: " + array);
for (JsonElement j :
array) {
expensep.add(gson.fromJson(j, ExpenseP.class));
}
rvRegs.setAdapter(new ExpenseAdapter());
rvRegs.setLayoutManager(new LinearLayoutManager(Expenses.this));
} else {
Log.d(TAG, "onResponse: Unsuccessful" + response.errorBody());
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.getMessage());
Log.d(TAG, "onFailure: " + t.getStackTrace());
Log.d(TAG, "onFailure: " + t.getLocalizedMessage());
}
});
}
class ExpenseAdapter extends RecyclerView.Adapter<ExpenseAdapter.VH> {
@NonNull
@Override
public VH onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new VH(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_expense, viewGroup, false));
}
@Override
public void onBindViewHolder(@NonNull final VH vh, int i) {
final ExpenseP ex = expensep.get(i);
vh.etFN.setText(ex.getUserId().split("-")[1]);
vh.etnm.setText(ex.getDate());
vh.etnm1.setText(ex.getAmount());
vh.leaves.setText(ex.getRemark());
vh.u_name.setText(ex.getName());
vh.u_department.setText(ex.getDepName());
if (ex.getStatus() == null) {
View.OnClickListener approveRejectClickListner = new View.OnClickListener() {
@Override
public void onClick(View v) {
int status = 0;
switch (v.getId()) {
case R.id.btnApprove:
status = 1;
vh.btnReject.setEnabled(true);
break;
case R.id.btnReject:
status = 0;
vh.btnApprove.setEnabled(true);
break;
}
JsonObject body = new JsonObject();
body.add("expense_id", new JsonPrimitive(ex.getExpenseId()));
body.add("status", new JsonPrimitive(status));
body.add("user_id", new JsonPrimitive(ex.getUserId()));
networkController.patchexpense("Bearer " + prefs.getString("token", null), prefs.getString("email", null), body).enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (response.code() == 200) {
Toast.makeText(Expenses.this, "Success", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
}
});
if(vh.btnApprove.isPressed()==true)
{
vh.btnApprove.setVisibility(View.GONE);
}
else if (vh.btnReject.isPressed()==true){
vh.btnReject.setVisibility(View.GONE);
}
}
};
vh.btnApprove.setOnClickListener(approveRejectClickListner);
vh.btnReject.setOnClickListener(approveRejectClickListner);
}
else
if (ex.getStatus() != 1) {
vh.btnReject.setText("Rejected");
vh.btnApprove.setVisibility(View.VISIBLE);
} else {
vh.btnApprove.setText("Approved");
vh.btnReject.setVisibility(View.VISIBLE);
}
}
@Override
public int getItemCount() {
return expensep.size();
}
class VH extends RecyclerView.ViewHolder {
TextView etFN, etnm, etnm1, leaves,u_name,u_department;
Button btnApprove, btnReject;
public VH(@NonNull View itemView) {
super(itemView);
etFN = itemView.findViewById(R.id.U_code);
etnm = itemView.findViewById(R.id.date);
etnm1 = itemView.findViewById(R.id.type);
leaves = itemView.findViewById(R.id.msg);
u_name=itemView.findViewById(R.id.U_name);
u_department=itemView.findViewById(R.id.U_dep);
btnApprove = itemView.findViewById(R.id.btnApprove);
btnReject = itemView.findViewById(R.id.btnReject);
}
}
}
}
解决方案
一种方法是利用多个 ViewHolders 和相应的视图类型。
当用户批准一个项目时,您可以通过更新相关项目来处理该批准点击,然后notifyItemChanged(getAdapterPosition())
告诉适配器该项目已更改。
您可以覆盖getItemViewType
并让它根据其状态返回布局。例如:
abstract class BaseViewHolder extends ViewHolder {
// Protected common views, like name, etc.
BaseViewHolder(View itemView) {
super(itemView);
// set up common views
}
public final void bindTo(ExpenseP expense) {
// set up common views
onBind(expense);
}
protected abstract void onBind(ExpenseP expense);
}
class AcceptedExpenseViewHolder extends BaseViewHolder {
// Protected accepted-only views...
BaseViewHolder(View itemView) {
super(itemView);
// set up accepted-only views...
}
@Override
protected void onBind(ExpenseP expense) {
// bind accepted-only views...
}
}
// Another class for RejectedExpenseViewHolder
// Another class for DefaultExpenseViewHolder (neither accepted or rejected)
然后,为每个定义一个布局。Android ID 不必是全球唯一的。我们可以通过对公共字段使用相同的 id 来利用这一点。例如,我们希望名称始终位于何处R.id.expense_name
或其他任何地方。
- 接受的费用项目.xml
- 拒绝费用项目.xml
- default_expense_item.xml
这些布局中的每一个都有一个唯一的标识符,我们可以将其用作 getItemViewType 内部的 ViewType 以及稍后在 onCreateViewHolder 中,而不是指定我们自己的:
int getItemViewType(position) {
ExpenseP item = data.get(position);
if (item.getStatus() == null) return R.layout.default_expense_item;
// ... etc.
}
BaseViewHolder onCreateViewHolder(...) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(viewType, parent, false);
switch (viewType) {
case R.layout.accepted_expense_item:
return new AcceptedExpenseViewHolder(itemView)
// etc.
}
}
如果您想传播点击以更新项目状态,您需要将某种侦听器传递给您的 ViewHolder,并在调用时适当地更新状态。然后您可以通知您的适配器发生了状态更改。例如:
interface DefaultListener {
void onAccepted(int position);
void onRejected(int position);
}
class DefaultExpenseViewHolder extends BaseViewHolder {
// Protected default-only views...
BaseViewHolder(View itemView, DefaultListener listener) {
super(itemView);
Button accepted = findViewById(R.id.accepted);
accepted.setOnClickListener(v -> listener.onAccepted(getAdapterPosition()));
}
//...
}
这会将它传播到定义 Listener 的任何地方。例如,在适配器的 onCreateViewHolder 中,您可以:
switch (viewType) {
case R.layout.accepted_expense_item:
return new AcceptedExpenseViewHolder(itemView, this)
}
并让适配器实现侦听器。然后,您可以在调用时适当地更新状态,然后通知适配器发生了更改。
例如:
void onAccepted(int position) {
ExpenseP item = data.get(position);
networkControllerStuff.accept(item, response -> {
// Check status, and update appropriately.
// Remember to replace the item in data with an updated item.
// And then:
notifyItemChanged(position)
})
}
TL; DR 这里我可以考虑处理更多的事情,但我在这里试图解决的一般方法是在这里使用多种视图类型来发挥你的优势,而不是试图操纵一些全局视图。
推荐阅读
- validation - 验证器到 TextField
- c++ - Qt3D画线消耗太多内存
- python - 如何从循环创建列表?
- matlab - 我可以编写没有后向函数的深度学习层吗?
- javascript - 在客户端 React 中存储 MSAL Graph API 令牌并重用它直到过期
- javascript - TypeError:模型不是构造函数
- sql-server - 使用 LIKE 关键字获取当前月份记录
- javascript - 图像调整大小不起作用(图像未保存在大小文件夹中(小,中,....)
- java - 如何在我的编码 android studio 项目中实现此代码 setDisplayName?
- magento2 - 提交扩展时如何通过技术审查 - Varnish 错误