前言

当我们阅读了ImageView源码后,发现Matrix的使用真的是很强大,几乎可以实现我们很多该有的功能,当我第一次看到这个效果的时候,第一想法就是ImageView的Matrix。通过比对了网上很多方案后,网上的方案还是比较复杂,如果我们巧用Matrix去做效果时,会发现其实代码也就100行左右就完美实现了效果,而且性能方面很不错,由于Gif图效果不佳,建议用代码跑一遍

效果展示

Android基础控件——ImageView的自定义,再次利用Matrix完美模仿小红书长图自动滚动效果

实现思路

我们的思想思路就是将两面相同的长图拼接成一张长图,通过平移播放这张长图,当我们的长图滑动到第二面图片的顶部时候,此时屏幕的顶部刚好和第二面图顶部相连接,这时候,我们马上将图片移到第一面,通过无缝的快速移动,骗过眼睛,实现我们自动滚动的效果,此时又重新从第一面开始滚动,如此循环就形成了自动滚动效果

准备工作

  • 准备好一张长图
  • 将两张同样的长图通过工具合成一张长图
  • 开始撸代码

合成前的长图

Android基础控件——ImageView的自定义,再次利用Matrix完美模仿小红书长图自动滚动效果

合成后的长图

Android基础控件——ImageView的自定义,再次利用Matrix完美模仿小红书长图自动滚动效果

实现步骤

1、快速使用

在xml直接配置的形式即可

<com.remo.mobile.framework.widget.ScrollerImageView     android:layout_width="match_parent"     android:layout_height="match_parent"     app:autoScroller="true"     app:scrollerImage="@drawable/login_bg_scroller_picture" /> 

2、自定义属性

<resources>     <declare-styleable name="ScrollerImageView">         <attr name="scrollerImage" format="reference" />         <attr name="autoScroller" format="boolean" />     </declare-styleable> </resources> 

3、定义属性

public class ScrollerImageView extends AppCompatImageView {      private Bitmap mBitmap; //当前滚动的图片     private Boolean autoScroller; //是否自动滚动          private int speed = 10; //当前滚动的速度     private float scale = 1f; //当前图片需要放大的比例     private double scrollerY = 0f; //当前滚动的Y坐标     private double onePictureHeight = 0; //一张图片的高度          public ScrollerImageView(Context context) {         this(context, null);     }          public ScrollerImageView(Context context, @Nullable AttributeSet attrs) {         this(context, attrs, 0);     }          public ScrollerImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);         initTypeArray(context, attrs);     } } 

4、获取自定义属性

private void initTypeArray(Context context, AttributeSet attrs) {     final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScrollerImageView);     int resId = typedArray.getResourceId(R.styleable.ScrollerImageView_scrollerImage, -1);     autoScroller = typedArray.getBoolean(R.styleable.ScrollerImageView_autoScroller, false);     mBitmap = BitmapFactory.decodeResource(context.getResources(), resId);     typedArray.recycle(); } 

5、更新尺寸和自动播放

onSizeChanged回调中,去更新我们的界面和开始滚动播放,由于我们的图片不一定是宽度充满整个屏幕,所以我们需要先缩放整个图片,通过updateCropMatrix缩放,接着通过runnable一直平移

@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {     super.onSizeChanged(w, h, oldw, oldh);     updateCropMatrix();     if (autoScroller) {         startScroller();     } }  private void updateCropMatrix() {     if (mBitmap == null) return;     setImageBitmap(mBitmap);      setScaleType(ScaleType.MATRIX);     Matrix mMatrix = new Matrix();      final int vHeight = getHeight() - getPaddingLeft() - getPaddingRight();//获取真实高度     final int vWidth = getWidth() - getPaddingTop() - getPaddingBottom();//获取真实宽度     final int dWidth = mBitmap.getWidth();     final int dHeight = mBitmap.getHeight();      scale = (float) vWidth / (float) dWidth;     onePictureHeight = (mBitmap.getHeight() * scale) / 2; //获取一面图片的高度      mMatrix.setScale(scale, scale); //先将图片宽缩放到View的同等大小     setImageMatrix(mMatrix); }  private Runnable scrollerRunnable = new Runnable() {     @Override     public void run() {         Matrix matrix = getImageMatrix();         if (scrollerY >= onePictureHeight) { //当前刚好到第二面顶部,里面平移回去到第一面             matrix.postTranslate(0, (float) onePictureHeight);             scrollerY = 0;         } else {             matrix.postTranslate(0, -1);             scrollerY++;         }         setImageMatrix(matrix);         invalidate();         getHandler().postDelayed(this, speed);     } };  private void startScroller() {     removeCallbacks(scrollerRunnable);     postDelayed(scrollerRunnable, speed); } 

6、释放内存

@Override protected void onDetachedFromWindow() {     super.onDetachedFromWindow();     stopScroller();     mBitmap.recycle();     mBitmap = null; } 

7、源码

public class ScrollerImageView extends AppCompatImageView {      private Bitmap mBitmap; //当前滚动的图片     private Boolean autoScroller; //是否自动滚动      private int speed = 10; //当前滚动的速度     private float scale = 1f; //当前图片需要放大的比例     private double scrollerY = 0f; //当前滚动的Y坐标     private double onePictureHeight = 0; //一张图片的高度      public ScrollerImageView(Context context) {         this(context, null);     }      public ScrollerImageView(Context context, @Nullable AttributeSet attrs) {         this(context, attrs, 0);     }      public ScrollerImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);         initTypeArray(context, attrs);     }      private void initTypeArray(Context context, AttributeSet attrs) {         final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScrollerImageView);         int resId = typedArray.getResourceId(R.styleable.ScrollerImageView_scrollerImage, -1);         autoScroller = typedArray.getBoolean(R.styleable.ScrollerImageView_autoScroller, false);         mBitmap = BitmapFactory.decodeResource(context.getResources(), resId);         typedArray.recycle();     }      private void updateCropMatrix() {         if (mBitmap == null) return;         setImageBitmap(mBitmap);          setScaleType(ScaleType.MATRIX);         Matrix mMatrix = new Matrix();          final int vHeight = getHeight() - getPaddingLeft() - getPaddingRight();//获取真实高度         final int vWidth = getWidth() - getPaddingTop() - getPaddingBottom();//获取真实宽度         final int dWidth = mBitmap.getWidth();         final int dHeight = mBitmap.getHeight();          scale = (float) vWidth / (float) dWidth;         onePictureHeight = (mBitmap.getHeight() * scale) / 2;          mMatrix.setScale(scale, scale); //先将图片宽缩放到View的同等大小         setImageMatrix(mMatrix);     }      private Runnable scrollerRunnable = new Runnable() {         @Override         public void run() {             Matrix matrix = getImageMatrix();             if (scrollerY >= onePictureHeight) {                 matrix.postTranslate(0, (float) onePictureHeight);                 scrollerY = 0;             } else {                 matrix.postTranslate(0, -1);                 scrollerY++;             }             setImageMatrix(matrix);             invalidate();             getHandler().postDelayed(this, speed);         }     };      private void startScroller() {         removeCallbacks(scrollerRunnable);         postDelayed(scrollerRunnable, speed);     }      private void stopScroller() {         removeCallbacks(scrollerRunnable);     }      @Override     protected void onDetachedFromWindow() {         super.onDetachedFromWindow();         stopScroller();         mBitmap.recycle();         mBitmap = null;     }      @Override     protected void onSizeChanged(int w, int h, int oldw, int oldh) {         super.onSizeChanged(w, h, oldw, oldh);         updateCropMatrix();         if (autoScroller) {             startScroller();         }     } } 
  • 版权声明:文章来源于网络采集,版权归原创者所有,均已注明来源,如未注明可能来源未知,如有侵权请联系管理员删除。

发表回复

后才能评论