图片根据内容中心点移动位置 ImageView

最近遇到一个问题:
我们在显示一张图片时,需要的效果像:
这里写图片描述
使用ImageView需要固定宽高比,但给定图片的宽高比是不一样的,怎么使内容在view 中,且图片不变形呢?这时候,单纯的使用ImageView的ScaleType属性不是让图片变形就是我们要显示的内容点被切除出去了。

ios方面:图片根据内容中心点移动位置:
https://github.com/totemtec/UIImageViewAligned

android方面:我试过两种方法

一:在设置ImageView的图片前,先根据获取的BitMap重新切出一个新的bitmap
使用的方法是createBitmap(bitmap, x, y,bitmap.getWidth() - x, (int) (bitmap.getWidth() * 0.65526316d));x,y是计算出来要从该位置开始切出一个一个长宽比例为0.65526316d 的bitmap后放入ImageView 中。
这个方法目前只对长比宽大的情况下有效,当宽比长大时会出错。而且对内存也有影响。

代码如下:

        //x1,y1是内容点在图片上的比例点
        double x1 = 0.6;
        double y1 = 0.7;
        //拿到获得的bitmap的宽高
        int imgw = bitmap.getWidth();
        int imgh = bitmap.getHeight();
        //计算内容点的坐标
        int w = (int) (imgw * x1);
        int h = (int) (imgh * y1);
        //计算我们切出bitmap的起始点,如果内容点原本就在imageview
        //的前半部分,我们就不需要在切出来了
        int x = (show_img.getWidth() / 2 >= w) ? 0 : (w - show_img.getWidth() / 2);
        int y = (show_img.getHeight() / 2 >= h) ? 0 : (h - show_img.getHeight() / 2);
        //新建一个bitmap
        Bitmap bi = Bitmap.createBitmap(bitmap, x, y, img1.getWidth() - x, (int) (img1.getWidth() * 0.65526316d));
        show_img.setImageBitmap(bi);

二:使用ImageView 的setImageMatrix()方法,将图片按计算出来的数据平移,将内容移动到ImageView区域,这里必须要将ImageView的属性android:scaleType=”matrix”设置为matrix。
这里使用imageLoader三方库来加载图片,记得使用前初始化它
imageLoader的使用情趣看其他人的、、

     //初始化imageLoader
     imageLoader.init(ImageLoaderConfiguration.createDefault(ImgListviewActivity.this));

下面是关键代码:

            //原图,我们常用的
            imageLoader.displayImage(list.get(position), holder.img,getOptions());
            //移动图,借用Listener能获取到它的bitmap
            imageLoader.displayImage(list.get(position), holder.show_img, getOptions(), new SimpleImageLoadingListener() {
                @Override
                public void onLoadingComplete(String imageUri, View view, Bitmap bitmap) {
                    super.onLoadingComplete(imageUri, view, bitmap);

                    ImageView imgv = (ImageView) view;
                    Matrix matrix = new Matrix();
                    float bitmapWidth = bitmap.getWidth();
                    float bitmapHeight = bitmap.getHeight();
                    //内容中心点所在图片的比例坐标
                    float Face_center_x = 0.5f;
                    float Face_center_y = 0.5f;
                    //缩放比例、使图片填充满view
                    float Scale = (imgv.getHeight() / bitmapHeight >= imgv.getWidth() / bitmapWidth) ? imgv.getHeight() / bitmapHeight : imgv.getWidth() / bitmapWidth;
                    matrix.postScale(Scale, Scale);
                    //缩放后的图片宽高
                    float scaleBitmapWidth = Scale * bitmapWidth;
                    float scaleBitmapHeight = Scale * bitmapHeight;

                    if (scaleBitmapWidth > scaleBitmapHeight) {  //宽度图
                        //移动的距离计算,下方有解释
                        float translate = (imgv.getWidth() / 2 >= Face_center_x * scaleBitmapWidth) ? 0 : ((Face_center_x * scaleBitmapWidth) - imgv.getWidth() / 2);
                        if (scaleBitmapWidth - translate <= imgv.getWidth()) {
                            translate = scaleBitmapWidth - imgv.getWidth();
                        }
                        matrix.postTranslate(-translate, 0);
                    } else {  //高度图
                        float translate = (imgv.getHeight() / 2 >= Face_center_y * scaleBitmapHeight) ? 0 : ((Face_center_y * scaleBitmapHeight) - imgv.getHeight() / 2);
                        if (scaleBitmapHeight - translate <= imgv.getHeight()) {
                            translate = scaleBitmapHeight - imgv.getHeight();
                        }
                        matrix.postTranslate(0, -translate);
                    }
                    imgv.setImageMatrix(matrix);
                    imgv.setImageBitmap(bitmap);

                }
            });

计算移动距离的公式

    float translate = (imgv.getWidth() / 2 >= Face_center_x * scaleBitmapWidth) ? 0 
                        : ((Face_center_x * scaleBitmapWidth) - imgv.getWidth() / 2);
     if (scaleBitmapWidth - translate <= imgv.getWidth()) {
                            translate = scaleBitmapWidth - imgv.getWidth();
                        }

这是宽度图的计算公式
imgv.getWidth() / 2 >= Face_center_x * scaleBitmapWidth 是判断内容中心点在左边多远,需不需要平移。如图
这里写图片描述
下面是判断会不会移动过头,造成右边出现空白的情况
if (scaleBitmapWidth - translate <= imgv.getWidth()) {
translate = scaleBitmapWidth - imgv.getWidth();
}
这里写图片描述

getOptions()是图片加载的一些情况

 public DisplayImageOptions getOptions() {
        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showStubImage(R.drawable.ic_launcher)          // 设置图片下载期间显示的图片
                .showImageForEmptyUri(R.drawable.ic_launcher)  // 设置图片Uri为空或是错误的时候显示的图片
                .showImageOnFail(R.drawable.ic_launcher)       // 设置图片加载过程中发生错误显示的图片
                .cacheInMemory(true)                        // 设置下载的图片是否缓存在内存中
                .cacheOnDisc(true)                           // 设置下载的图片是否缓存在SD卡中
                .build();                                   // 创建配置过得DisplayImageOption对象
        return options;
    }

设置View的宽高方法:

    private int width = 0;
    private int height = 0;
    private void scaleImage(ImageView view) {
        //获取屏幕的宽高
        WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        if (width == 0) {
            width = outMetrics.widthPixels;
        }
        if (height == 0) {
            height = (int) (width * 0.65526316d);
        }
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
        if (params == null) {
            params = new LinearLayout.LayoutParams(width, height);
        } else {
            params.height = height;
            params.width = width;
        }
        view.setLayoutParams(params);
    }

这个方法每个图片加载都会走三遍,我也不清楚情况、、、

如果有其他方法或者你发现的缺陷,请告知我,谢谢。
项目下载地址:
http://download.csdn.net/detail/zp0203/9573126

谢谢指教!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下段代码 可以拖动,但缩放和旋转时会闪退,请改正 public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: // 手指压下屏幕 mode = MODE.DRAG; // 查找被点击的图片 int index = event.getActionIndex(); float x = event.getX(index); float y = event.getY(index); CustomBitmap clickedBitmap = findClickedBitmap(x, y); if (clickedBitmap != null) { // 切换操作对象 _bitmaps.remove(clickedBitmap); _bitmaps.add(clickedBitmap); // 记录ImageView当前的移动位置 currentMatrix.set(clickedBitmap.matrix); clickedBitmap.matrix.set(currentMatrix); clickedBitmap.startPoint.set(x, y); _curCustomBitmap = clickedBitmap; } postInvalidate(); break; case MotionEvent.ACTION_POINTER_DOWN: // 当屏幕上还有触点(手指),再有一个手指压下屏幕 mode = MODE.ZOOM; // 记录位图的旋转角度和缩放倍数 _curCustomBitmap.oldRotation = rotation(event); _curCustomBitmap.startDis = distance(event); if (_curCustomBitmap.startDis > 10f) { // 获取缩放中心点的坐标 float x1 = event.getX(0); float y1 = event.getY(0); float x2 = event.getX(1); float y2 = event.getY(1); _curCustomBitmap.midPoint.set((x1 + x2) / 2, (y1 + y2) / 2); // 记录ImageView当前的缩放倍数 currentMatrix.set(_curCustomBitmap.matrix); } break; case MotionEvent.ACTION_MOVE: // 手指在屏幕移动,该事件会不断地触发 if (mode == MODE.DRAG) { // 移动图片 float dx = event.getX() - _curCustomBitmap.startPoint.x; float dy = event.getY() - _curCustomBitmap.startPoint.y; _curCustomBitmap.matrix.set(currentMatrix); _curCustomBitmap.matrix.postTranslate(dx, dy); } else if (mode == MODE.ZOOM) { // 缩放和旋转图片 float endDis = distance(event); float rotation = rotation(event) - _curCustomBitmap.oldRotation; if (endDis > 10f) { float scale = endDis / _curCustomBitmap.startDis; _curCustomBitmap.matrix.set(currentMatrix); _curCustomBitmap.matrix.postScale(scale, scale, _curCustomBitmap.midPoint.x, _curCustomBitmap.midPoint.y); _curCustomBitmap.matrix.postRotate(rotation, _curCustomBitmap.midPoint.x, _curCustomBitmap.midPoint.y); } } break; case MotionEvent.ACTION_POINTER_UP: // 有手指离开屏幕,但屏幕还有触点(手指) mode = MODE.NONE; break; } invalidate(); return true;
最新发布
06-06
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值