长图加载要用到一个关键的类BitmapRegionDecoder,长图加载会使用到bitmap内存复用, 比如view大小是440*654,图片的宽高是440*12000,那么这个时候就要获取图片的宽和高, 跟view的宽和高进行对比,获取到一个缩小比例,那么会得到宽一个比例,高一个比例,用大的比例作为缩放因子,然后配合手势滑动滑动长图
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Rect; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import android.widget.Scroller; import java.io.IOException; import java.io.InputStream; public class BigView extends View implements GestureDetector.OnGestureListener, View.OnTouchListener { private static final String TAG = "BigView"; private Scroller mScroller; private GestureDetector mGestureDetector; private BitmapFactory.Options mOptions; private Rect mRect; private int mImageWidth; private int mImageHeight; private BitmapRegionDecoder mDecoder; private int mViewWidth; private int mViewHeight; private float mScale; private Bitmap bitmap; public BigView(Context context) { this(context, null, 0); } public BigView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public BigView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //指定要加载的矩形区域 mRect = new Rect(); //解码图片的配置 mOptions = new BitmapFactory.Options(); //手势 mGestureDetector = new GestureDetector(context, this); setOnTouchListener(this); // 滑动帮助 mScroller = new Scroller(context); } /** * 由使用者输入一张图片 输入流 * * @param is */ public void setImage(InputStream is) { //先读取原图片的 宽、高 mOptions.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, mOptions); mImageWidth = mOptions.outWidth; mImageHeight = mOptions.outHeight; //复用 内存复用 mOptions.inMutable = true; //设置像素格式为 rgb565 mOptions.inPreferredConfig = Bitmap.Config.RGB_565; mOptions.inJustDecodeBounds = false; //创建区域解码器 用于区域解码图片 try { mDecoder = BitmapRegionDecoder.newInstance(is, false); } catch (IOException e) { e.printStackTrace(); } requestLayout(); } /** * 测量 view的大小 * * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //获得测量的view的大小 mViewWidth = getMeasuredWidth(); mViewHeight = getMeasuredHeight(); //如果解码器是null 表示没有设置过要现实的图片 if (null == mDecoder) { return; } //确定要加载的图片的区域 mRect.left = 0; mRect.top = 0; mRect.right = mImageWidth; // Log.e(TAG,"缩放因子="+(mViewWidth*1.0f/mImageWidth*1.0f)); // Log.e(TAG,"缩放因子="+(mViewHeight*1.0f/mImageHeight*1.0f)); //获得缩放因子 mScale = mViewWidth / (float) mImageWidth; // 需要加载的高 * 缩放因子 = 视图view的高 // x * mScale = mViewHeight mRect.bottom = (int) (mViewHeight / mScale); Log.e(TAG,"l="+mRect.left); Log.e(TAG,"t="+mRect.top); Log.e(TAG,"r="+mRect.right); Log.e(TAG,"b="+mRect.bottom); } /** * 把图片画上去 * * @param canvas */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 如果解码器是null 表示没有设置过要现实的图片 if (null == mDecoder) { return; } //复用上一张bitmap Log.e(TAG,"复用上一张bitmap="+bitmap); mOptions.inBitmap = bitmap; //解码指定区域 bitmap = mDecoder.decodeRegion(mRect, mOptions); //使用矩阵 对图片进行 缩放 Matrix matrix = new Matrix(); matrix.setScale(mScale, mScale); //画出来 canvas.drawBitmap(bitmap, matrix, null); } /** * 手指按下屏幕的回调 * @param e * @return */ @Override public boolean onDown(MotionEvent e) { //如果滑动还没有停止 强制停止 if (!mScroller.isFinished()){ mScroller.forceFinished(true); } //继续接收后续事件 return true; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public void onLongPress(MotionEvent e) { } /** * 手指 不离开屏幕 拖动 * @param e1 手指按下去 的事件 -- 获取开始的坐标 * @param e2 当前手势事件 -- 获取当前的坐标 * @param distanceX x轴 方向移动的距离 * @param distanceY y方向移动的距离 * @return */ @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // 手指从下往上 图片也要往上 distanceY是负数, top 和 bottom 在减 // 手指从上往下 图片也要往下 distanceY是正数, top 和 bottom 在加 //改变加载图片的区域 mRect.offset(0, (int) distanceY); //bottom大于图片高了, 或者 top小于0了 if (mRect.bottom > mImageHeight){ mRect.bottom = mImageHeight; mRect.top = mImageHeight-(int) (mViewHeight / mScale); } if (mRect.top < 0){ mRect.top = 0; mRect.bottom = (int) (mViewHeight / mScale); } //重绘 invalidate(); return false; } /** * 手指离开屏幕 滑动 惯性 * @param e1 * @param e2 * @param velocityX 速度 每秒x方向 移动的像素 * @param velocityY y * @return */ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { /** * startX: 滑动开始的x坐标 * startY: 滑动开始的y坐标 * 两个速度 * minX: x方向的最小值 * max 最大 * y */ //计算器 mScroller.fling(0,mRect.top, 0,(int)-velocityY, 0,0,0, mImageHeight - (int) (mViewHeight / mScale)); return false; } //获取计算结果并且重绘 @Override public void computeScroll() { //已经计算结束 return if (mScroller.isFinished()){ return; } //true 表示当前动画未结束 if (mScroller.computeScrollOffset()){ // mRect.top = mScroller.getCurrY(); mRect.bottom = mRect.top+ (int) (mViewHeight / mScale); invalidate(); } } @Override public boolean onTouch(View v, MotionEvent event) { //交由手势处理 return mGestureDetector.onTouchEvent(event); } }
如果是面试关键二点,第一个要说出来这个类,第二个要知道使用了内存复用.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持靠谱客。
最后
以上就是洁净楼房最近收集整理的关于android实现长图加载效果的全部内容,更多相关android实现长图加载效果内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复