2017-07-11 31 views
10

Özel şekilli bir görüntü görüntüsü oluşturdum. Scrollview içinde kullanırsanız iyi çalışır. Ama onu geridönüşümde kullanmaya çalıştığımda gözlemlediğim tuhaf bir davranış var. Aşağı kaydırılmadıkça görüntüler çekilmez ve gösterilmez (bkz. 1. resim). Kaydettiğinizde de aynı şey olur.RecyclerView

Bu boşlukların nasıl önleneceğini bilmek istiyorum. Lütfen bana nerede yanlış olduğumu gösterebilir misin? Yardım için teşekkürler.

İlk durum veya yukarı kaydırma sonra:

Initial state

aşağı kaydırma sonra:

After scrolling down

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(); 
     } 
    } 
} 

Burada örnek bir uygulamanın dahil eğer ilgilendi sorunu göstermek için

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"/> 

Burada satır öğesi XML için kesim düzeni kullanmalıdır

<?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"/> 

cevap

8

bazı After resea rch ve denemek için Path değerlerinin özellikle kenarlık için doğru ve iyi tasarlanmadığını anladım. Bazı durumlarda birbirleriyle örtüşüyorlar ve bunun resimlerin doğru çizilmemesine neden olduğunu düşündüm.

Görünümü yeniden tasarladım ve bazı iyileştirmeler yaptım. Gelecekteki okuyucular için burada son kod:

/** 
* Created by santalu on 7/4/17. 
* 
* Note: if position set NONE mask won't be applied 
* 
* POSITION DIRECTION 
* 
* TOP   LEFT | RIGHT 
* BOTTOM  LEFT | RIGHT 
* LEFT  TOP | BOTTOM 
* RIGHT  TOP | BOTTOM 
*/ 

public class DiagonalImageView extends AppCompatImageView { 

    private static final String TAG = DiagonalImageView.class.getSimpleName(); 

    public static final int NONE = 0; 
    public static final int TOP = 1; 
    public static final int RIGHT = 2; 
    public static final int BOTTOM = 4; 
    public static final int LEFT = 8; 

    private final Path mClipPath = new Path(); 
    private final Path mBorderPath = new Path(); 

    private final Paint mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 

    private int mPosition; 
    private int mDirection; 
    private int mOverlap; 
    private int mBorderColor; 
    private int mBorderSize; 

    private boolean mBorderEnabled; 

    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.DiagonalImageView); 
     try { 
      mPosition = a.getInteger(R.styleable.DiagonalImageView_di_position, NONE); 
      mDirection = a.getInteger(R.styleable.DiagonalImageView_di_direction, RIGHT); 
      mOverlap = a.getDimensionPixelSize(R.styleable.DiagonalImageView_di_overlap, 0); 
      mBorderSize = a.getDimensionPixelSize(R.styleable.DiagonalImageView_di_borderSize, 0); 
      mBorderColor = a.getColor(R.styleable.DiagonalImageView_di_borderColor, Color.BLACK); 
      mBorderEnabled = a.getBoolean(R.styleable.DiagonalImageView_di_borderEnabled, false); 

      mBorderPaint.setColor(mBorderColor); 
      mBorderPaint.setStyle(Style.STROKE); 
      mBorderPaint.setStrokeWidth(mBorderSize); 
     } finally { 
      a.recycle(); 
     } 
    } 

    public void set(int position, int direction) { 
     if (mPosition != position || mDirection != direction) { 
      mClipPath.reset(); 
      mBorderPath.reset(); 
     } 
     mPosition = position; 
     mDirection = direction; 
     postInvalidate(); 
    } 

    public void setPosition(int position) { 
     if (mPosition != position) { 
      mClipPath.reset(); 
      mBorderPath.reset(); 
     } 
     mPosition = position; 
     postInvalidate(); 
    } 

    public void setDirection(int direction) { 
     if (mDirection != direction) { 
      mClipPath.reset(); 
      mBorderPath.reset(); 
     } 
     mDirection = direction; 
     postInvalidate(); 
    } 

    public void setBorderEnabled(boolean enabled) { 
     mBorderEnabled = enabled; 
     postInvalidate(); 
    } 

    @Override protected void onDraw(Canvas canvas) { 
     if (mClipPath.isEmpty()) { 
      super.onDraw(canvas); 
      return; 
     } 

     int saveCount = canvas.save(); 
     canvas.clipPath(mClipPath); 
     super.onDraw(canvas); 
     if (!mBorderPath.isEmpty()) { 
      canvas.drawPath(mBorderPath, mBorderPaint); 
     } 
     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 (mClipPath.isEmpty()) { 
      int width = getMeasuredWidth(); 
      int height = getMeasuredHeight(); 

      if (width <= 0 || height <= 0) { 
       return; 
      } 

      mClipPath.reset(); 
      mBorderPath.reset(); 

      switch (mPosition) { 
       case TOP: 
        if (mDirection == LEFT) { 
         mClipPath.moveTo(0, 0); 
         mClipPath.lineTo(width, mOverlap); 
         mClipPath.lineTo(width, height); 
         mClipPath.lineTo(0, height); 

         if (mBorderEnabled) { 
          mBorderPath.moveTo(0, 0); 
          mBorderPath.lineTo(width, mOverlap); 
         } 
        } else { 
         mClipPath.moveTo(0, mOverlap); 
         mClipPath.lineTo(width, 0); 
         mClipPath.lineTo(width, height); 
         mClipPath.lineTo(0, height); 

         if (mBorderEnabled) { 
          mBorderPath.moveTo(0, mOverlap); 
          mBorderPath.lineTo(width, 0); 
         } 
        } 
        break; 
       case RIGHT: 
        if (mDirection == TOP) { 
         mClipPath.moveTo(0, 0); 
         mClipPath.lineTo(width, 0); 
         mClipPath.lineTo(width - mOverlap, height); 
         mClipPath.lineTo(0, height); 

         if (mBorderEnabled) { 
          mBorderPath.moveTo(width, 0); 
          mBorderPath.lineTo(width - mOverlap, height); 
         } 
        } else { 
         mClipPath.moveTo(0, 0); 
         mClipPath.lineTo(width - mOverlap, 0); 
         mClipPath.lineTo(width, height); 
         mClipPath.lineTo(0, height); 

         if (mBorderEnabled) { 
          mBorderPath.moveTo(width - mOverlap, 0); 
          mBorderPath.lineTo(width, height); 
         } 
        } 
        break; 
       case BOTTOM: 
        if (mDirection == LEFT) { 
         mClipPath.moveTo(0, 0); 
         mClipPath.lineTo(width, 0); 
         mClipPath.lineTo(width, height - mOverlap); 
         mClipPath.lineTo(0, height); 

         if (mBorderEnabled) { 
          mBorderPath.moveTo(0, height); 
          mBorderPath.lineTo(width, height - mOverlap); 
         } 
        } else { 
         mClipPath.moveTo(0, 0); 
         mClipPath.lineTo(width, 0); 
         mClipPath.lineTo(width, height); 
         mClipPath.lineTo(0, height - mOverlap); 

         if (mBorderEnabled) { 
          mBorderPath.moveTo(0, height - mOverlap); 
          mBorderPath.lineTo(width, height); 
         } 
        } 
        break; 
       case LEFT: 
        if (mDirection == TOP) { 
         mClipPath.moveTo(0, 0); 
         mClipPath.lineTo(width, 0); 
         mClipPath.lineTo(width, height); 
         mClipPath.lineTo(mOverlap, height); 

         if (mBorderEnabled) { 
          mBorderPath.moveTo(0, 0); 
          mBorderPath.lineTo(mOverlap, height); 
         } 
        } else { 
         mClipPath.moveTo(mOverlap, 0); 
         mClipPath.lineTo(width, 0); 
         mClipPath.lineTo(width, height); 
         mClipPath.lineTo(0, height); 

         if (mBorderEnabled) { 
          mBorderPath.moveTo(mOverlap, 0); 
          mBorderPath.lineTo(0, height); 
         } 
        } 
        break; 
      } 

      mClipPath.close(); 
      mBorderPath.close(); 
     } 
    } 
} 

Güncelleme: Ben durumda bir kitaplık olarak Github Bu yayınlanan yorumun için Diagonal ImageView

1

activity_main.xml bağlantı https://github.com/florent37/DiagonalLayout

<com.github.florent37.diagonallayout.DiagonalLayout 
    android:layout_width="match_parent" 
    android:layout_height="250dp" 
    android:elevation="10dp" 
    app:diagonal_angle="20" 
    app:diagonal_position="top" 
    app:diagonal_direction="right"> 

    <ImageView 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:scaleType="centerCrop" 
     android:src="@drawable/mountains" /> 

+1

Teşekkür gerekir. Evet bu kütüphanenin farkındayım. Ama ekran görüntüsünden görebildiğiniz gibi, geridönüşüm öğelerinin birbiriyle örtüşmesini sağladım ve tüm öğelerin kendi bölücüleri (turuncu çizgi) var. Ve her bir öğenin kendi sınırlamalarına uyduğundan ve doğru bir şekilde çizildiğinden emin olmak için, üst üste gelme yüksekliğiyle hesaplanan görüntü görünümünün klip yolu ve bölücü yolu. Sadece bakış açımdan veya geridönüşüm uygulamalarından neyin yanlış olduğunu bilmek istiyorum. Ama öneri için teşekkürler – santalu

+0

Ayrıca bu kitaplıkta da aynı sorun oluşur. Bunu geri dönüşüm bölümünde kullanmayı deneyin. – santalu

+0

köşegen konumunu ayarladınız mı, XML bu köşegen gibi olmalıdır: diagonal_position = "bottom". Emin değilim, ancak son endeksi kontrol ederseniz, hangi diyagonal konumun en altta ayarlandığı yer için farklı düzeni kullanabilirsiniz. – farhana