Android 展开和折叠项目时,RecyclerView中的分隔线行为异常

Android 展开和折叠项目时,RecyclerView中的分隔线行为异常,android,android-recyclerview,divider,Android,Android Recyclerview,Divider,展开和折叠我的回收视图项目时,会多次绘制分隔线或项目透支。 此外,在展开和收拢视图时,分割线的厚度也会减小。 我的问题是每次在Recyclerview中展开和折叠项时都会绘制分隔线。 那么,如果已经绘制分隔线,是否可以防止绘制分隔线? 展开项目时,分隔线将根据视图移动 下面是我的RecyclerView装饰类用于分隔线 public class SeparatorDecoration extends RecyclerView.ItemDecoration { private fina

展开和折叠我的回收视图项目时,会多次绘制分隔线或项目透支。

此外,在展开和收拢视图时,分割线的厚度也会减小。

我的问题是每次在Recyclerview中展开和折叠项时都会绘制分隔线。 那么,如果已经绘制分隔线,是否可以防止绘制分隔线? 展开项目时,分隔线将根据视图移动

下面是我的RecyclerView装饰类用于分隔线

public  class SeparatorDecoration extends RecyclerView.ItemDecoration {

    private final Paint mPaint;

    /**
     * Create a decoration that draws a line in the given color and width between the items in the view.
     * @param context  a context to access the resources.
     * @param color    the color of the separator to draw.
     * @param heightDp the height of the separator in dp.
     */
    public SeparatorDecoration(@NonNull Context context, @ColorInt int color,
                               @FloatRange(from = 0, fromInclusive = false) float heightDp) {
        mPaint = new Paint();
        mPaint.setColor(color);
        final float thickness = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                heightDp, context.getResources().getDisplayMetrics());
        mPaint.setStrokeWidth(thickness);
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
        // we want to retrieve the position in the list
        final int position = params.getViewAdapterPosition();
        // and add a separator to any view but the last one
        if (position <state.getItemCount()) {
            outRect.set(40, 0, 40, (int) mPaint.getStrokeWidth()); // left, top, right, bottom
        } else {
            outRect.setEmpty(); // 0, 0, 0, 0
        }
    }

    @Override
    public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        final int offset = (int) (mPaint.getStrokeWidth() / 2);

        // this will iterate over every visible view
        for (int i = 0; i < parent.getChildCount(); i++) {
            // get the view
            final View view = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
            // get the position
            final int position = params.getViewAdapterPosition();

            // and finally draw the separator
            if (position < parent.getChildCount()) {
                final int ty = (int)(view.getTranslationY() + 0.5f);
                final int top = view.getBottom() - params.bottomMargin + ty;
                final int bottom = top + (int) mPaint.getStrokeWidth();
                c.drawLine(view.getLeft(), view.getBottom() + offset, view.getRight(), view.getBottom() + offset, mPaint);
            }

        }
    }
}

公共类分隔符Decoration扩展了RecyclerView.ItemDecoration{
私人最终油漆;
/**
*创建一个装饰,在视图中的项目之间以给定的颜色和宽度绘制一条线。
*@param context是访问资源的上下文。
*@param color要绘制的分隔符的颜色。
*@param heightDp分离器的高度,单位为dp。
*/
公共分隔符分解(@NonNull上下文,@ColorInt color,
@FloatRange(from=0,from inclusive=false)浮点高度dp){
mPaint=新油漆();
mPaint.setColor(颜色);
最终浮子厚度=类型值。应用尺寸(类型值。复杂单位),
heightDp,context.getResources().getDisplayMetrics());
mPaint.设定行程宽度(厚度);
}
@凌驾
public void getItemOffsets(Rect outRect、View View、RecyclerView父级、RecyclerView.State){
final RecycleView.LayoutParams params=(RecycleView.LayoutParams)视图。getLayoutParams();
//我们要检索列表中的位置
final int position=params.getViewAdapterPosition();
//并在除最后一个视图外的任何视图中添加分隔符
if(位置通知记录列表){
this.context=上下文;
this.deleteNotificationListener=监听器;
this.notificationRecords=notificationRecords列表;
}
@非空
@凌驾
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup父级,int-viewType){
LayoutInflater LayoutInflater=LayoutInflater.from(parent.getContext());
log(5,标记为“oncreate”);
View listItem=LayoutFlater.inflate(R.layout.display\u notification\u recycler\u View\u list\u item,父项,false);
返回新的NotificationViewHolder(列表项);
}
@RequiresApi(api=Build.VERSION\u code.N)
@凌驾
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder,int位置){
NotificationDetails通知=notificationRecords.get(位置);
NotificationViewHolder viewHolder=(NotificationViewHolder)holder;
String currentDateString=DateFormat.getDateInstance().format(Long.parseLong(notification.getTimeStamp());
字符串filePath=generateFilePath(notification.getFileName());
位图myBitmap=BitmapFactory.decodeFile(文件路径);
@SuppressLint(“SimpleDataFormat”)
DateFormat DateFormat=新的SimpleDateFormat(“hh:mm aa”);
String time=dateFormat.format(Long.parseLong(notification.getTimeStamp());
if(notification.isExpanded()){
viewHolder.expandCollapseImageView.setImageDrawable(context.getDrawable(ImageDrawable.getDrawable(“向上箭头”));
expandView(viewHolder.notificationImageview);
}
否则{
viewHolder.expandCollapseImageView.setImageDrawable(context.getDrawable(ImageDrawable.getDrawable(“向下箭头”));
折叠视图(viewHolder.notificationImageview);
}
viewHolder.notificationImageview.setImageBitmap(myBitmap);
viewHolder.notificationTextView.setText(notification.getMessage());
viewHolder.notificationTimeTextView.setText(时间);
Calendar now=Calendar.getInstance();
日历日期=Calendar.getInstance();
date.setTimeInMillis(Long.parseLong(notification.getTimeStamp());
viewHolder.expandCollapseImageView.setOnClickListener(新视图.OnClickListener()的缩写){
@凌驾
公共void onClick(视图v){
if(notification.isExpanded()){
通知.setExpanded(false);
viewHolder.expandCollapseImageView.setImageDrawable(context.getDrawable(ImageDrawable.getDrawable(“向下箭头”));
viewHolder.notificationTextView.setMaxLines(1);
(职位)变更;
}
否则{
notification.setExpanded(true);
viewHolder.expandCollapseImageView.setImageDrawable(context.getDrawable(ImageDrawable.getDrawable(“向上箭头”));
viewHolder.notificationTextView.setMaxLines(整数.MAX_值);
(职位)变更;
}
}
});
if(now.get(Calendar.DATE)=DATE.get(Calendar.DATE))
viewHolder.notificationDateTextView.setText(“今天”);
else if(now.get(Calendar.DATE)-DATE.get(Calendar.DATE)==1)
viewHolder.notificationDateTextView.setText(“昨天”);
其他的
viewHolder.notificationDateTextView.setText(currentDateString);
if(notification.getTitle()==null)
viewHolder.notificationTitleTextView.setText(“标题”);
其他的
viewHolder.notificationTitleTextView.setText(notification.getTitle());
}
私有字符串生成器


public class DisplayNotificationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

        private Context context;
        private List<NotificationDetails> notificationRecords;

        private DeleteNotificationListener deleteNotificationListener;


        private String TAG = DisplayNotificationAdapter.class.getSimpleName();


        

        interface DeleteNotificationListener {
            void updateNotificationList(List<NotificationDetails> details);
        }

        public DisplayNotificationAdapter(Context context, DeleteNotificationListener listener, List < NotificationDetails > notificationRecordsList) {
            this.context = context;
            this.deleteNotificationListener = listener;
            this.notificationRecords = notificationRecordsList;
        }


        @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder (@NonNull ViewGroup parent, int viewType){
            LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
            AndroidLogger.log(5,TAG,"oncreate");
            View listItem = layoutInflater.inflate(R.layout.display_notification_recycler_view_list_item, parent, false);
            return new NotificationViewHolder(listItem);
        }

        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        public void onBindViewHolder (@NonNull RecyclerView.ViewHolder holder,int position){
            
            NotificationDetails notification = notificationRecords.get(position);
            NotificationViewHolder viewHolder = (NotificationViewHolder) holder;
            String currentDateString = DateFormat.getDateInstance().format(Long.parseLong(notification.getTimeStamp()));
           
            String filePath=generateFilePath(notification.getFileName());
            Bitmap myBitmap = BitmapFactory.decodeFile(filePath);
            @SuppressLint("SimpleDateFormat")
            DateFormat dateFormat = new SimpleDateFormat("hh:mm aa");
            
            
            String time = dateFormat.format(Long.parseLong(notification.getTimeStamp()));
           
            if (notification.isExpanded()) {
                viewHolder.expandCollapseImageView.setImageDrawable(context.getDrawable(ImageDrawable.getDrawable("Up Arrow")));
                expandView(viewHolder.notificationImageview);
               
            }
            else {
                viewHolder.expandCollapseImageView.setImageDrawable(context.getDrawable(ImageDrawable.getDrawable("Down Arrow")));
                collapseView(viewHolder.notificationImageview);
            }
            viewHolder.notificationImageview.setImageBitmap(myBitmap);
            viewHolder.notificationTextView.setText(notification.getMessage());
            viewHolder.notificationTimeTextView.setText(time);
            Calendar now = Calendar.getInstance();
            Calendar date = Calendar.getInstance();
            date.setTimeInMillis(Long.parseLong(notification.getTimeStamp()));
           
            viewHolder.expandCollapseImageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(notification.isExpanded()) {
                        notification.setExpanded(false);
                        viewHolder.expandCollapseImageView.setImageDrawable(context.getDrawable(ImageDrawable.getDrawable("Down Arrow")));
                       
                        viewHolder.notificationTextView.setMaxLines(1);
                        notifyItemChanged(position);
                    }
                    else {
                        notification.setExpanded(true);
                        viewHolder.expandCollapseImageView.setImageDrawable(context.getDrawable(ImageDrawable.getDrawable("Up Arrow")));
                      
                        viewHolder.notificationTextView.setMaxLines(Integer.MAX_VALUE);
                        notifyItemChanged(position);
                    }
                }
            });

            if (now.get(Calendar.DATE) == date.get(Calendar.DATE))
                viewHolder.notificationDateTextView.setText("Today");
            else if (now.get(Calendar.DATE) - date.get(Calendar.DATE) == 1)
                viewHolder.notificationDateTextView.setText("Yesterday");
            else
                viewHolder.notificationDateTextView.setText(currentDateString);
            if(notification.getTitle()==null)
                viewHolder.notificationTitleTextView.setText("title");
            else
                viewHolder.notificationTitleTextView.setText(notification.getTitle());
        }

    private String generateFilePath(String fileName) {
        
        File imageFileDirectory = context.getDir("image", Context.MODE_PRIVATE); //Creating an internal dir;
        if (!imageFileDirectory.exists()) {
            imageFileDirectory.mkdirs();
        }
        /*
         * app server provide "U" file name after we set read status they provide same file name as "R"
         */
        String createFilePath = imageFileDirectory + "/" + fileName;
       
        return createFilePath;
    }


    public void removeSingleNotification ( int position){
            DatabaseHelper databaseHelper = new DatabaseHelper(context);
            databaseHelper.deleteSingleNotificationRecord(notificationRecords.get(position).getId());
            notificationRecords.remove(position);
            deleteNotificationListener.updateNotificationList(notificationRecords);
            notifyDataSetChanged();
        }
       
         
        private void removeFromList (String id) {
            for (NotificationDetails detail : notificationRecords) {
                if (detail.getId().equalsIgnoreCase(id))
                    notificationRecords.remove(detail);
            }
        }


        @Override
        public int getItemCount () {
            
        return notificationRecords.size();
    }

        public  void expandView(final View v) {
           
            int matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec(((View) v.getParent()).getWidth(), View.MeasureSpec.EXACTLY);
            int wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
            v.measure(matchParentMeasureSpec, wrapContentMeasureSpec);
            final int targetHeight = v.getMeasuredHeight();

        // Older versions of android (pre API 21) cancel animations for views with a height of 0.
            v.getLayoutParams().height = 1;
            v.setVisibility(View.VISIBLE);
            Animation a = new Animation()
            {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    v.getLayoutParams().height = interpolatedTime == 1
                            ? ViewGroup.LayoutParams.WRAP_CONTENT
                            : (int)(targetHeight * interpolatedTime);
                    v.requestLayout();
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        // Expansion speed of 1dp/ms
       a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density));
        
            v.startAnimation(a);
    }

    public  void collapseView(final View v) {
        //collapse(pos);
        final int initialHeight = v.getMeasuredHeight();

        Animation a = new Animation()
        {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                if(interpolatedTime == 1){
                    v.setVisibility(View.GONE);
                }else{
                    v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
                    v.requestLayout();
                }
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        // Collapse speed of 1dp/ms
        a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
       
        v.startAnimation(a);
    }
   
    public static class NotificationViewHolder extends RecyclerView.ViewHolder {
        private TextView notificationTextView, notificationDateTextView, notificationTimeTextView, notificationTitleTextView;
        private ImageView notificationImageview,expandCollapseImageView;
        private ConstraintLayout parent;
        public NotificationViewHolder(@NonNull View itemView) {
            super(itemView);
            notificationTextView = itemView.findViewById(R.id.notification_text_view);
            notificationDateTextView = itemView.findViewById(R.id.notification_date_text_view);
            notificationTimeTextView = itemView.findViewById(R.id.notification_time_text_view);
            notificationTitleTextView = itemView.findViewById(R.id.notification_title_text_view);
            notificationImageview = itemView.findViewById(R.id.notification_image_view);
            expandCollapseImageView = itemView.findViewById(R.id.expand_collapse_arrow);
            parent = itemView.findViewById(R.id.notification_parent);
        }
    }
}
<View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:id="@+id/view_div"
        android:background="@color/grey"