您的位置:首页 > 移动开发 > Android开发

Android:自定义imageview实现两条线裁剪图片,不在区域内显示阴影

2016-09-24 21:32 751 查看
MainActivity

package com.example.customimageview;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.ScrollView;

public class MainActivity extends Activity {

private static final String TAG = "customimageview";
private MyImageView img;
private ScrollView sv;
private static final String CROP_IMAGE_PATH = "/storage/emulated/0/3.png";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);

Bitmap bmp = BitmapFactory.decodeFile(CROP_IMAGE_PATH);
img = (MyImageView) findViewById(R.id.long_pic);
img.setImageBitmap(bmp);
Button btn = (Button) findViewById(R.id.btn);
Log.i(TAG, "onCreate ");
sv = (ScrollView) findViewById(R.id.scrollView);
btn.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i(TAG, "onClick(View v) enter");
savedBitmap(img.getClippedBitmap());
}
});

sv.setOnTouchListener(new View.OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
img.getParent().requestDisallowInterceptTouchEvent(false);
return false;
}
});
}

private void savedBitmap(Bitmap bitmap) {
Log.i(TAG, "savedBitmap(Bitmap bitmap)");
if (bitmap != null) {
Log.i(TAG, "bitmap != null");
try {
long current = System.currentTimeMillis();
Date date = new Date(current);
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String filename = format.format(date);
StringBuilder builder = new StringBuilder();
builder.append(filename);
builder.append(".png");
filename = builder.toString();
File fileImage = new File("/sdcard/", filename);
if (!fileImage.exists()) {
fileImage.createNewFile();
Log.i(TAG, "image file created");
}
FileOutputStream out = new FileOutputStream(fileImage);
if (out != null) {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
Intent media = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(fileImage);
media.setData(contentUri);
this.sendBroadcast(media);
Log.i(TAG, "screen image saved");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
Log.i(TAG, "savedBitmap(Bitmap bitmap) = null");
}
}
}


activity_mainxml文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >

<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="save" />

<ScrollView
android:id="@+id/scrollView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btn"
android:layout_centerHorizontal="true" >

<LinearLayout
android:id="@+id/Linear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_below="@+id/top_text"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:orientation="vertical" >

<com.example.customimageview.MyImageView
android:id="@+id/long_pic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</LinearLayout>
</ScrollView>

</RelativeLayout>


自定义ImageView实现裁剪图片

package com.example.customimageview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ImageView;

/**
* 图片剪裁控件; 注意事项: 1.在为ClipImageView设置图片时(调用setImageResource(),
* setImageDrawable(), setImageBitmap()),要注意图片的大小,即注意Bitmap可能导致 程序出现oom的问题。
* 2.如对剪裁图片质量无过高要求,建议调用setImageResourceSecure(), setImageDrawableSecure(),
* setImageBitmapSecure()设置图片。
*
*/
public class MyImageView extends ImageView {

private static final String TAG = "customimageview";

/**
* mClipFrameBorderWidth:剪裁框的边框宽度;TOUCH_FIELD:触摸范围;UP_DOWN_LENGTH:剪裁最小高度
*/
private final float density = getResources().getDisplayMetrics().density; // 密度
private float mClipFrameBorderWidth = 1 * density; // 剪裁框的边框宽度
private static final float TOUCH_FIELD = 20f;
private static final float UP_DOWN_LENGTH = 50f;

/**
* 初始图片大小
*/
private int imWidth;
private int imHeight;

private boolean showClipFrame = true; // 是否显示剪裁框

private String mClipFrameColor = "#FFFFFFFF"; // 剪裁框的边框颜色
private String mShadowColor = "#99000000"; // 阴影颜色

private Paint mShadowPaint;
private Paint mClipFramePaint;
/**
* 剪裁框外的阴影
*/
private Rect mRectTopShadow;
private Rect mRectBottomShadow;
/**
* 剪裁框:顶部条和底部条
*/
private int mTopLineY = 100; // 默认顶部条Y坐标
private int mBottomLineY = 200; // 默认底部条Y坐标
private int mLineWidth;

private PointF mLastPoint = new PointF();

private int mShadowUpY; // 顶部阴影高度
private int mShadowDownY; // 底部阴影高度
/**
* 设置在ImageView中的Bitmap
*/
private Bitmap source;

/**
* 触摸事件位置
*/
private int touchPos;
private static final int POS_TOP = 1;
private static final int POS_BOTTOM = 2;
private static final int POS_CENTER = 3;
private boolean mInterceptTouchEvent;

public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setAdjustViewBounds(true);

initPaint();
initRect();

post(new Runnable() {

@Override
public void run() {
imWidth = getWidth();
imHeight = getHeight();

Log.i(TAG, "imWidth: " + imWidth + " imHeight: " + imHeight);
mLineWidth = imWidth;
resolveClipFrameSize(); // 必要步骤,校正剪裁框大小,底部条不能超过图片大小

}
});
}

private void initPaint() {
mShadowPaint = new Paint();
mShadowPaint.setColor(Color.parseColor(mShadowColor));

mClipFramePaint = new Paint();
mClipFramePaint.setStyle(Paint.Style.STROKE); // 设置为空心
mClipFramePaint.setStrokeWidth(mClipFrameBorderWidth); // 设置边框宽度
setClipFrameColor(Color.BLUE); // 设置颜色
}

private void initRect() {
/**
* 阴影区域
*/
mRectTopShadow = new Rect();
mRectBottomShadow = new Rect();
}

/**
* 设置剪裁框外的阴影
*
* @param x
*            剪裁框当前的左上角X坐标
* @param y
*            剪裁框当前的左上角Y坐标
*/

/**
* 方法已对resId指向的图片进行压缩处理, 用此方法设置图片,剪裁后的相片质量相对 较差,但可简单避免Bitmap的OOM;如需
* 对原图进行裁剪,请直接调用setImageResource()
*
* @param resId
*/
public void setImageResourceSecure(int resId) {
Bitmap bm = BitmapFactory.decodeResource(getResources(), resId);
setImageBitmap(processBitmap(bm));
}

/**
* 方法已对drawable指向的图片进行压缩处理, 用此方法设置图片,剪裁后的相片质量相对 较差,但可简单避免Bitmap的OOM;如需
* 对原图进行裁剪,请直接调用setImageDrawable()
*
* @param drawable
*/
public void setImageDrawableSecure(Drawable drawable) {
if (drawable == null)
throw new IllegalArgumentException("drawable 不能为null");
BitmapDrawable bd = (BitmapDrawable) drawable;
setImageBitmap(processBitmap(bd.getBitmap()));
}

/**
* 方法已对bm指向的图片进行压缩处理, 用此方法设置图片,剪裁后的相片质量相对 较差,但可简单避免Bitmap的OOM;如需
* 对原图进行裁剪,请直接调用setImageBitmap()
*
* @param bm
*/
public void setImageBitmapSecure(Bitmap bm) {
setImageBitmap(processBitmap(bm));
}

/**
* 对Bitmap进行简单的处理,适当地压缩图片大小
*
* @param bm
* @return
*/
private Bitmap processBitmap(Bitmap bm) {
if (bm == null)
throw new IllegalArgumentException("bitmap 不能为null");

int screenWidth = getResources().getDisplayMetrics().widthPixels;
int screenHeight = getResources().getDisplayMetrics().heightPixels;
int bmWidth = bm.getWidth();
int bmHeight = bm.getHeight();
if (bmWidth < screenWidth || bmHeight < screenHeight)
return bm;

float scale = (float) screenWidth / bmWidth;
Bitmap bitmap = Bitmap.createScaledBitmap(bm, screenWidth, (int) (bmHeight * scale), true);
bm.recycle();
return bitmap;
}

/**
* 获取设置在ClipImageView中的Bitmap
*
* @return
*/
public Bitmap getSourceBitmap() {
if (source != null)
return source;

Drawable d = getDrawable();
if (d == null) {
return null;
}

BitmapDrawable bd = (BitmapDrawable) d;
source = bd.getBitmap();
return source;
}

/**
* 获取ImageView对原图的缩放比例
*
* @return
*/
public float getScale() {
if (getSourceBitmap() == null)
return 0f;

int bmWidth = source.getWidth();
int bmHeight = source.getHeight();
float scale = Math.min((float) bmWidth / imWidth, (float) bmHeight / imHeight);
return scale;
}

/**
* 获取剪裁好的bitmap
*
* @return
*/
public Bitmap getClippedBitmap() {
float scale = getScale();
Log.i(TAG, "getClippedBitmap() scale: " + scale);
if (scale > 0 && source != null) {
/*
* Log.i(TAG, "ClipImageUtils.clipImage() currX: "+currX+" currY: "+
* currY+" mClipFrameWidth: "+mClipFrameWidth+" mClipFrameHeight: "
* +mClipFrameHeight);
*/

return ClipImageUtils.clipImage(source, 0, mTopLineY, // 剪裁图片
imWidth, mBottomLineY - mTopLineY, scale);
}
return null;
}

/**
* 设置剪裁框边框的颜色,支持#RRGGBB #AARRGGBB 'red', 'blue', 'green', 'black', 'white',
* 'gray', 'cyan', 'magenta', 'yellow', 'lightgray', 'darkgray', 'grey',
* 'lightgrey', 'darkgrey', 'aqua', 'fuschia', 'lime', 'maroon', 'navy',
* 'olive', 'purple', 'silver', 'teal'
*
* @param color
*/
public void setClipFrameColor(String color) {
mClipFramePaint.setColor(Color.parseColor(color));
}

public void setClipFrameColor(int color) {
mClipFramePaint.setColor(color);
}

/**
* 校正裁剪框的高,使其不能超过View的高
*/
private void resolveClipFrameSize() {
mBottomLineY = mBottomLineY >= imHeight ? imHeight : mBottomLineY;
}

/**
* 设置剪裁框的边框宽度
*
* @param w
*/
public void setClipFrameBorderWidth(float w) {
w = w < 0 ? 0 : w;
mClipFrameBorderWidth = w;
mClipFramePaint.setStrokeWidth(mClipFrameBorderWidth);
}

/**
* 顶部条的Y坐标
*
* @return
*/
public float getContentX() {
return mTopLineY;
}

/**
* 底部条的Y坐标
*
* @return
*/
public float getContentY() {
return mBottomLineY;
}

/**
* 获取剪裁内容的宽度
*
* @return
*/
public int getContentWidth() {
return (mBottomLineY - mTopLineY);
}

public int getImWidth() {
return imWidth;
}

public int getImHeight() {
return imHeight;
}

/**
* 设置是否显示剪裁框
*
* @param f
*/
public void setShowClipFrame(boolean f) {
showClipFrame = f;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (showClipFrame) {
drawShadowRegion(canvas);
drawClipFrame(canvas);
}
}

/**
* 绘制剪裁框外的阴影
*
* @param canvas
*/
private void drawShadowRegion(Canvas canvas) {
mRectTopShadow.set(0, 0, imWidth, mTopLineY);
mRectBottomShadow.set(0, mBottomLineY, imWidth, imHeight);
canvas.drawRect(mRectTopShadow, mShadowPaint);
canvas.drawRect(mRectBottomShadow, mShadowPaint);
}

/**
* 绘制剪裁框
*
* @param canvas
*/
private void drawClipFrame(Canvas canvas) {
canvas.drawLine(0, mTopLineY, mLineWidth, mTopLineY, mClipFramePaint);
canvas.drawLine(0, mBottomLineY, mLineWidth, mBottomLineY, mClipFramePaint);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setLastPosition(event);

touchPos = detectTouchPosition(event.getX(), event.getY());
getParent().requestDisallowInterceptTouchEvent(mInterceptTouchEvent);

break;
case MotionEvent.ACTION_MOVE:
onActionMove(event.getX(), event.getY());
setLastPosition(event);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}

private void onActionMove(float x, float y) {
// TODO Auto-generated method stub
float deltaX = x - mLastPoint.x;
float deltaY = y - mLastPoint.y;

switch (touchPos) {
case POS_CENTER:

break;
case POS_TOP:
resetTop(deltaY);
break;
case POS_BOTTOM:
resetBottom(deltaY);
break;
default:

break;
}

invalidate();

}

private void resetBottom(float deltaY) {
// TODO Auto-generated method stub
mBottomLineY += deltaY;
fixBottomLine();
}

private void fixBottomLine() {
// TODO Auto-generated method stub
if (mBottomLineY > imHeight) {
mBottomLineY = imHeight;
}

if ((mBottomLineY - mTopLineY) < 2 * UP_DOWN_LENGTH) {
mBottomLineY = (int) (mTopLineY + 2 * UP_DOWN_LENGTH);
}
}

private void resetTop(float deltaY) {
// TODO Auto-generated method stub
mTopLineY += deltaY;
fixTopLine();
}

private void fixTopLine() {
// TODO Auto-generated method stub
if (mTopLineY < 0) {
mTopLineY = 0;
}

if ((mBottomLineY - mTopLineY) < 2 * UP_DOWN_LENGTH) {
mTopLineY = (int) (mBottomLineY - 2 * UP_DOWN_LENGTH);
}

}

private void setLastPosition(MotionEvent event) {
mLastPoint.x = event.getX();
mLastPoint.y = event.getY();
}

/**
* 判断触摸位置
*
* @param x
* @param y
* @return
*/
private int detectTouchPosition(float x, float y) {
if (x > TOUCH_FIELD && x < mLineWidth - TOUCH_FIELD && y > mTopLineY + TOUCH_FIELD
&& y < mBottomLineY - TOUCH_FIELD) {

mInterceptTouchEvent = false;  //不处理该区域的事件;scrollview处理

return POS_CENTER;
}

if (x > TOUCH_FIELD && x < mLineWidth - TOUCH_FIELD && y > mTopLineY - TOUCH_FIELD
&& y < mTopLineY + TOUCH_FIELD) {

mInterceptTouchEvent = true;  //处理该区域的事件

return POS_TOP;
}
if (x > TOUCH_FIELD && x < mLineWidth - TOUCH_FIELD && y > mBottomLineY - TOUCH_FIELD
&& y < mBottomLineY + TOUCH_FIELD) {

mInterceptTouchEvent = true;  //处理该区域的事件

return POS_BOTTOM;
}
return -1;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android imageview
相关文章推荐