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