Я создал пользовательское изображение в форме. Он отлично работает, если вы используете его в scrollview. Но когда я попытался использовать его в recyclerview, там странное поведение я наблюдал. Изображения не получают ничью и показывают пробел (см. 1-е изображение), если вы не прокрутите вниз (см. 2-е изображение). То же самое происходит при прокрутке вверх.
Я хочу знать, как избежать этих пробелов. Не могли бы вы указать мне, где я делаю неправильно? Спасибо за помощь.
Начальное состояние или после прокрутки:
После прокрутки вниз:
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
/**
* Created by santalu on 7/4/17.
*/
public class DiagonalImageView extends AppCompatImageView {
public static final int TOP = 0;
public static final int MIDDLE = 1;
public static final int BOTTOM = 2;
private final Path mClipPath = new Path();
private final Path mLinePath = new Path();
private final Paint mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private int mPosition;
private int mOverlap;
private int mLineColor;
private int mLineSize;
private boolean mMaskEnabled = true;
public DiagonalImageView(Context context) {
super(context);
init(context, null);
}
public DiagonalImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (attrs == null) {
return;
}
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ShowCaseImageView);
try {
mPosition = a.getInt(R.styleable.DiagonalImageView_di_position, TOP);
mOverlap = a.getDimensionPixelSize(R.styleable.DiagonalImageView_di_overlap, 0);
mLineSize = a.getDimensionPixelSize(R.styleable.DiagonalImageView_di_lineSize, 0);
mLineColor = a.getColor(R.styleable.DiagonalImageView_di_lineColor, Color.BLACK);
mLinePaint.setColor(mLineColor);
mLinePaint.setStyle(Style.STROKE);
mLinePaint.setStrokeWidth(mLineSize);
} finally {
a.recycle();
}
}
public void setPosition(int position, boolean maskEnabled) {
mMaskEnabled = maskEnabled;
setPosition(position);
}
public void setPosition(int position) {
if (mPosition != position) {
mClipPath.reset();
mLinePath.reset();
}
mPosition = position;
}
@Override protected void onDraw(Canvas canvas) {
int saveCount = canvas.getSaveCount();
canvas.clipPath(mClipPath);
super.onDraw(canvas);
canvas.drawPath(mLinePath, mLinePaint);
canvas.restoreToCount(saveCount);
}
@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (!changed) {
return;
}
if (mMaskEnabled && mClipPath.isEmpty()) {
int width = getMeasuredWidth();
int height = getMeasuredHeight();
if (width <= 0 || height <= 0) {
return;
}
switch (mPosition) {
case TOP:
mClipPath.moveTo(0, 0);
mClipPath.lineTo(width, 0);
mClipPath.lineTo(width, height - mOverlap);
mClipPath.lineTo(0, height);
mLinePath.moveTo(0, height);
mLinePath.lineTo(width, height - mOverlap);
break;
case MIDDLE:
mClipPath.moveTo(0, mOverlap);
mClipPath.lineTo(width, 0);
mClipPath.lineTo(width, height - mOverlap);
mClipPath.lineTo(0, height);
mLinePath.moveTo(0, height);
mLinePath.lineTo(width, height - mOverlap);
break;
case BOTTOM:
mClipPath.moveTo(0, mOverlap);
mClipPath.lineTo(width, 0);
mClipPath.lineTo(width, height);
mClipPath.lineTo(0, height);
break;
}
mClipPath.close();
mLinePath.close();
}
}
}
Я включаю здесь пример приложения, чтобы продемонстрировать проблему, если вы заинтересованы
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.santalu.showcaseimageview.ShowCaseImageView;
public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int overlap = getResources().getDimensionPixelSize(R.dimen.overlap_size);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new OverlapItemDecoration(-overlap));
recyclerView.setAdapter(new SampleAdapter(this));
}
static class SampleAdapter extends RecyclerView.Adapter<SampleAdapter.ViewHolder> {
private final Context mContext;
SampleAdapter(Context context) {
mContext = context;
}
@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item, parent, false));
}
@Override public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(position);
}
@Override public int getItemCount() {
return 7;
}
class ViewHolder extends RecyclerView.ViewHolder {
DiagonalImageView image;
//int overlap;
ViewHolder(View itemView) {
super(itemView);
image = (DiagonalImageView) itemView.findViewById(R.id.image);
//overlap = -mContext.getResources().getDimensionPixelSize(R.dimen.overlap_size);
}
void bind(int position) {
boolean maskEnabled = getItemCount() > 1;
//MarginLayoutParams params = (MarginLayoutParams) image.getLayoutParams();
if (position == 0) {
image.setPosition(ShowCaseImageView.TOP, maskEnabled);
//params.setMargins(0, 0, 0, 0);
} else if (position == getItemCount() - 1) {
image.setPosition(ShowCaseImageView.BOTTOM, maskEnabled);
//params.setMargins(0, overlap, 0, 0);
} else {
image.setPosition(ShowCaseImageView.MIDDLE, maskEnabled);
//params.setMargins(0, overlap, 0, 0);
}
//image.setLayoutParams(params);
}
}
}
static class OverlapItemDecoration extends RecyclerView.ItemDecoration {
private int mOverlap;
OverlapItemDecoration(int overlap) {
mOverlap = overlap;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
if (parent.getChildAdapterPosition(view) != 0) {
outRect.top = mOverlap;
}
}
}
}
item.xml
<?xml version="1.0" encoding="utf-8"?>
<com.santalu.diagonalimageview.DiagonalImageView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="@dimen/image_height"
android:scaleType="centerCrop"
android:src="@drawable/demo"
app:csi_lineColor="@color/deep_orange"
app:csi_lineSize="@dimen/line_size"
app:csi_overlap="@dimen/overlap_size"/>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>