我的管理应用有费用要求类的东西。我要实现的是,当用户单击“批准”按钮时,其上的文本应更改为“已批准”,而“拒绝”按钮应消失,反之亦然。 我无法实现这一点,我尝试了所有方法,但每次尝试解决此问题都获得了更奇怪的输出。请附上您所做更改的原因,因为这会对我有所帮助。谢谢
这是我的代码
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);
}
}
}
}
答案 0 :(得分:1)
一种实现此目的的方法是利用多个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
或其他任何内容。
这些布局中的每个布局都有一个唯一的标识符,我们可以将其用作getItemViewType以及以后的onCreateViewHolder中的ViewType,而不必指定自己的标识符:
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)
}
并让Adapter实现侦听器。然后,您可以在调用它们时适当地更新状态,然后通知适配器发生了更改。
例如:
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我想在这里处理更多的事情,但是我试图在这里讲解的一般方法是使用多个视图类型以在这里发挥自己的优势,而不是尝试操纵某些全局视图。