import 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.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Scroller;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by yly on 2019/9/25.
*/
public class BigView extends View implements GestureDetector.OnGestureListener,View.OnTouchListener{
private Scroller mScroller;
private GestureDetector mGesture;
private BitmapFactory.Options mOptions;
private Rect mRect;
private int mImageWidth;
private int mImageHeight;
private BitmapRegionDecoder mDecode;
private int mViewWidth;
private int mViewHeight;
private int mScale;
private Bitmap mBitmap;
public BigView(Context context) {
this(context,null);
}
public BigView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public BigView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//设置BitView所需要的一些成员变量
mRect=new Rect();
//内存复用
mOptions=new BitmapFactory.Options();
//手势识别
mGesture=new GestureDetector(context,this);
mScroller=new Scroller(context);
setOnTouchListener(this);
}
//设置图片得到图片信息
public void setImage(InputStream is){
mOptions.inJustDecodeBounds=false;
BitmapFactory.decodeStream(is,null,mOptions);
//获取宽高,不能把整张图片加载进去
mImageWidth=mOptions.outWidth;
mImageHeight=mOptions.outHeight;
//开启复用
mOptions.inMutable=true;
//设置RGB,//比4个8大一倍,把透明通道给去掉了当然565质量也会降低,还是要根据自己的需求
//4个8和565用的是最多的
mOptions.inPreferredConfig= Bitmap.Config.RGB_565;
mOptions.inJustDecodeBounds=true;
//区域解码器
try {
mDecode= BitmapRegionDecoder.newInstance(is,false);
} catch (IOException e) {
e.printStackTrace();
}
requestLayout();
}
//3,开始测量,等比例的缩放,必须要知道手机的宽高,得到View的宽高,要加载的图片到底要是什么样子
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//得到View的大小
mViewWidth=getMeasuredWidth();
mViewHeight=getMeasuredHeight();
//确定加载图片的区域,没有缩放图片
mRect.left=0;
mRect.top=0;
mRect.right=getMeasuredWidth();
//计算缩放因子
mScale=mViewWidth/mImageWidth;
mRect.bottom=mViewHeight/mScale;
}
//4,画出具体内容
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//判断解码器是不是为空
if (mDecode==null){
//如果解码器为空表示没有设置过图片
return ;
}
//内存复用
mOptions.inBitmap= mBitmap;
//指定解码的区域
mBitmap=mDecode.decodeRegion(mRect,mOptions);
Matrix matrix=new Matrix();
matrix.setScale(mScale,mScale);
canvas.drawBitmap(mBitmap,matrix,null);
}
//第五步,处理手势,这时已经可以把绿色显示,处理点击时间
@Override
public boolean onTouch(View v, MotionEvent event) {
//直接交给手势处理
return mGesture.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent e) {
//滑动的时候点击停下俩
if (!mScroller.isFinished()){
mScroller.forceFinished(true);
}
return true;
}
//处理滑动事件,第一第二参数手指按下获取当前坐标,第三第四表示xy周移动距离
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//上下移动改变显示的区域
mRect.offset(0, (int) distanceY);
//处理到达顶部和底部情况
if (mRect.bottom>mImageHeight){
mRect.bottom=mImageHeight;
mRect.top=mImageHeight-(mViewHeight/mScale);
}
if (mRect.top<0){
mRect.top=0;
mRect.bottom=mViewHeight/mScale;
}
invalidate();
return false;
}
//第八步,处理惯性问题
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
mScroller.fling(0,mRect.top,0, (int) -velocityY,0,0,0,mImageHeight-mViewHeight/mScale);
return false;
}
//第九步,处理计算结果
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.isFinished()){
return;
}
//滑动没有结束就要处理
if (mScroller.computeScrollOffset()){
//就要去加载
mRect.top=mScroller.getCurrY();
mRect.bottom=mRect.top+mViewHeight/mScale;
invalidate();
}
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
}
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import com.example.demoproject.loadbigImage.BigView;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private static List<String> mList;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BigView bigView = findViewById(R.id.bigView);
try {
InputStream in = getAssets().open("big.png");
bigView.setImage(in);
} catch (IOException e) {
e.printStackTrace();
}
}
}