具有设置可见性的回收器视图



我的管理应用程序有一个费用请求。我想要实现的是,当用户单击批准按钮时,其上的文本应更改为"已批准",拒绝按钮应消失,反之亦然。 我无法实现这一目标,我已经尝试了所有方法,但每次尝试解决此问题时都会获得更奇怪的输出。请在您的更改中附上原因,因为这会对我有所帮助。谢谢

这是我的代码

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);
}
}
}
}

一种方法是利用多个ViewHolder和相应的视图类型。

当用户批准项目时,您可以通过更新相关项目,然后利用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或其他什么。

  • accepted_expense_item.xml
  • rejected_expense_item.xml
  • default_expense_item.xml

这些布局中的每一个都有一个唯一的标识符,我们可以将其用作getItemViewType中的ViewType,稍后在CreateViewHolder中使用它,而不是指定我们自己的:

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()));
}
//...
}

这会将其传播到定义侦听器的任何位置。例如,在适配器的 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:我能想到处理的事情还有很多,但我在这里试图传达的一般方法是在这里使用多种视图类型来发挥您的优势,而不是试图操纵一些全局视图。

最新更新