Android:自定义imageview实现两条线裁剪图片,不在区域内显示阴影
2016-09-24 21:32
751 查看
MainActivity
activity_mainxml文件
自定义ImageView实现裁剪图片
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实现图片圆形 ,椭圆和矩形圆角显示
- Android ImageView实现图片裁剪和显示功能
- Android自定义ImageView实现图片圆形 ,椭圆和矩形圆角显示
- Android自定义ImageView实现图片圆形 ,椭圆和矩形圆角显示
- Android可以动态控制图片显示区域的自定义ImageView
- android自定义View实现图片上传进度显示(仿手机QQ上传效果)
- android 自定义imageview实现 图片放大缩小
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- ImageView的使用,实现本地图片的适屏显示和裁剪功能。
- android 自定义ImageView实现图片缩放边界回弹和缩小回弹
- android自定义View实现图片上传进度显示(仿手机QQ上传效果)
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- 【Android 开发】:UI控件之 ImageView 实现适屏和裁剪图片的功能
- 【Android】自定义ImageView实现图片的平移、缩放、旋转(手势操作)
- android自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- android 自定义ImageView实现图片手势滑动、多点触摸缩放
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果 .
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果