前言
当我们阅读了ImageView源码后,发现Matrix的使用真的是很强大,几乎可以实现我们很多该有的功能,当我第一次看到这个效果的时候,第一想法就是ImageView的Matrix。通过比对了网上很多方案后,网上的方案还是比较复杂,如果我们巧用Matrix去做效果时,会发现其实代码也就100行左右就完美实现了效果,而且性能方面很不错,由于Gif图效果不佳,建议用代码跑一遍
效果展示
实现思路
我们的思想思路就是将两面相同的长图拼接成一张长图,通过平移播放这张长图,当我们的长图滑动到第二面图片的顶部时候,此时屏幕的顶部刚好和第二面图顶部相连接,这时候,我们马上将图片移到第一面,通过无缝的快速移动,骗过眼睛,实现我们自动滚动的效果,此时又重新从第一面开始滚动,如此循环就形成了自动滚动效果
准备工作
- 准备好一张长图
- 将两张同样的长图通过工具合成一张长图
- 开始撸代码
合成前的长图
合成后的长图
实现步骤
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(); } } }
- 版权声明:文章来源于网络采集,版权归原创者所有,均已注明来源,如未注明可能来源未知,如有侵权请联系管理员删除。