首页 > 解决方案 > Android工作室,回收视图

问题描述

我在 android studio 中有一些错误。当我尝试将符号 ('*') 添加到特殊项目时,它还会将该符号添加到从第一个开始放置在 +14 中的项目。如果有人能解决这个问题,我会很高兴。有关更多信息,您可以查看此链接,我在其中描述了问题。 https://youtu.be/CJFkt-Cck1A

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {

    private static final String TAG = "RecyclerViewAdapter";
    private Context context;
    private List<WorkDayItem> workDayItemList;

    //Complete
    public RecyclerViewAdapter(Context context, List<WorkDayItem> workDayItemList) {
        this.context = context;
        this.workDayItemList = workDayItemList;
    }

    //Complete
    //Here we create view- itemWorkday and inflate it by layout- item_one_work_day
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View itemWorkDay = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_one_work_day, parent, false);
        MyViewHolder myViewHolder = new MyViewHolder(itemWorkDay);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        Log.d(TAG, "onBindViewHolder: called." + (position + 1) + "\n" + workDayItemList.get(position).toString());

        final WorkDayItem workDayItem = workDayItemList.get(position);
        String dateStart = (String) DateFormat.format("dd.MM", workDayItem.getDateStart());
        String timeStart = (String) DateFormat.format("HH:mm", workDayItem.getDateStart());
        String timeEnd = (String) DateFormat.format("HH:mm", workDayItem.getDateEnd());

        //Convert data from firebase String format to int hours and minutes format.
        Double convertingDataFromFirebase;
        try {
            convertingDataFromFirebase = Double.parseDouble(new DecimalFormat("##.##").format(workDayItem.getCount_hours()));
        } catch (NumberFormatException e) {
            convertingDataFromFirebase = 0.0;
        }

        int hours = convertingDataFromFirebase.intValue();

        convertingDataFromFirebase = (convertingDataFromFirebase - convertingDataFromFirebase.intValue()) * 60;
        int minutes = convertingDataFromFirebase.intValue();

        //Check if current item have description
        if (workDayItemList.get(position).getDesc().length() > 2) {
            Log.i(TAG, "TESTER: desc dote added");
            holder.doteOfDesc.setVisibility(View.VISIBLE);
        }


        holder.dayPosition.setText((position + 1) + "");
        holder.dateStart.setText(dateStart);
        holder.timeStart.setText(timeStart);
        holder.timeEnd.setText(timeEnd);
        holder.countOfHours.setText(hours + ":" + minutes);


        //On click on current hold open alert dialog with some functions
        holder.parentLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                initializeAlertDialogForItem(workDayItem, holder);
            }
        });

    }


    //initialize data about current work day and have button for changing information
    private void initializeAlertDialogForItem(final WorkDayItem workDayItem, final MyViewHolder holder) {

        //Initialize alert dialog
        final AlertDialog alertDialog = new AlertDialog.Builder(context).create();
        View itemWork = LayoutInflater.from(context)
                .inflate(R.layout.ad_item_desc, null, false);
        alertDialog.setView(itemWork);
        alertDialog.show();


        //initialize alert dialog buttons and views
        final ImageButton change = alertDialog.findViewById(R.id.itemAD_Edit);
        final ImageButton delete = alertDialog.findViewById(R.id.itemAD_Delete);

        TextView description = alertDialog.findViewById(R.id.itemADDescription);
        TextView date = alertDialog.findViewById(R.id.itemADDate);
        TextView from = alertDialog.findViewById(R.id.itemADFrom);
        TextView to = alertDialog.findViewById(R.id.itemADTO);

        String timeStart = (String) (DateFormat.format("HH:mm", workDayItem.getDateStart()));
        String timeEnd = (String) (DateFormat.format("HH:mm", workDayItem.getDateEnd()));
        String dateStart = (String) (DateFormat.format("dd.MM.yyyy", workDayItem.getDateStart()));


        date.setText(dateStart);
        from.setText(timeStart);
        to.setText(timeEnd);
        description.setText(workDayItem.getDesc());
        //Change button
        change.setOnClickListener(new View.OnClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void onClick(View v) {
                AlertDialogReport userReport = new AlertDialogReport(context, "replace-remove", workDayItem);
                userReport.initializeAlertDialog();
                alertDialog.dismiss();
            }
        });

        delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Delete data from firebase

                Login.fc.databaseReference.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                            String itemTime = "" + workDayItem.getDateStart().getTime();
                            String firebaseTime = "" + snapshot.child("dateStart").child("time").getValue();
                            if (itemTime.equals(firebaseTime)) {
                                Login.fc.databaseReference.child(snapshot.getKey()).removeValue();
                            }
                        }
                    }

                    @Override
                    public void onCancelled(@NonNull DatabaseError databaseError) {
                    }
                });
                //Delete data from SqLiteDatabase
                MySQLDataBase dataBase = new MySQLDataBase(context);
                dataBase.deleteItem(workDayItem);

                //Finish with alert dialog and notify user
                alertDialog.dismiss();
                Toast.makeText(context, R.string.item_deleted, Toast.LENGTH_SHORT).show();
                holder.parentLayout.removeAllViews();
            }
        });

    }


    //Complete
    @Override
    public int getItemCount() {
        return workDayItemList.size();
    }


    //Complete
    //Here we catch our view and getting reference between view and our objects
    public class MyViewHolder extends RecyclerView.ViewHolder {
        private LinearLayout parentLayout;
        private TextView doteOfDesc, dayPosition, dateStart, timeStart, timeEnd, countOfHours;

        public MyViewHolder(View view) {
            super(view);
            doteOfDesc = view.findViewById(R.id.itemDote);
            dayPosition = view.findViewById(R.id.itemDayPosition);
            dateStart = view.findViewById(R.id.itemDateStart);
            timeStart = view.findViewById(R.id.itemStartHour);
            timeEnd = view.findViewById(R.id.itemEndHour);
            countOfHours = view.findViewById(R.id.itemCountOfHours);
            parentLayout = view.findViewById(R.id.itemWorkDay);
        }
    }

}

标签: javaandroidandroid-studioandroid-recyclerview

解决方案


尝试添加这个:

    //Check if current item have description
    if (workDayItemList.get(position).getDesc().length() > 2) {
                Log.i(TAG, "TESTER: desc dote added");
                holder.doteOfDesc.setVisibility(View.VISIBLE);
            }
    else if( workDayItemList.get(position).getDesc().length() < 2 
             && holder.doteOfDesc.getVisibility()== View.VISIBLE ){
     holder.doteOfDesc.setVisibility(View.GONE);
}

发生这种情况的原因是RecyclerView创建ViewHolders了覆盖整个屏幕所需的数量加上一些额外的(在您的情况下为 12)然后通过将值重新绑定到视图来重用它们。并且您设置doteOfDescView.VISIBLE2. ViewHolder,但永远不要将其设置回View.GONE,这就是为什么每次ViewHolder重用它都会doteOfDesc可见。

更漂亮的版本:

  Boolean hasDescription = workDayItemList.get(position).getDesc().length() > 2;
  holder.doteOfDesc.setVisibility( hasDescription ? View.VISIBLE : View.GONE);

推荐阅读