自定义控件-截屏当前界面
来源:互联网 发布:情义我心知 编辑:程序博客网 时间:2024/06/05 16:55
声明一下:先贴出的一个图片裁剪的类,忘记是从哪位大神那拿的代码了,见谅哈!如果有人知道的话,回复一下链接,我再补上,哈哈...
看下效果:
以下是在图片裁剪类的原型上修改过的:
import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Rect;import android.graphics.Region;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import com.hmy.android.allforme.util.DimenUtil;/** * Created by hmy */public class CropImageView extends View { protected Context mContext; private DimenUtil dimenUtil; // 在touch重要用到的点, private float mX_1 = 0; private float mY_1 = 0; // 当前状态 private TouchStatus touchStatus = TouchStatus.STATUS_SINGLE; // 默认裁剪的宽高 private int cropWidth = 0; private int cropHeight = 0; //手指触摸位置 public TouchPosition touchPosition = TouchPosition.EDGE_NONE; protected Drawable mDrawable;//被裁剪对象 protected FloatDrawable mFloatDrawable;//裁剪层 protected Rect mDrawableSrc = new Rect();// 图片Rect变换时的Rect protected Rect mDrawableDst = new Rect();// 图片Rect protected Rect mDrawableFloat = new Rect();// 裁剪层的Rect private boolean isTouchInSquare = true;//当前触点是否在裁剪框内 protected boolean isFrist = true;// protected float oriRationWH = 0;// private boolean isCropEnable = true; public void setCropEnable(boolean cropEnable) { this.isCropEnable = cropEnable; } /** * 手指触摸状态 */ public enum TouchStatus { STATUS_SINGLE,//单指触摸 STATUS_MULTI_START,//多指触摸开始 STATUS_MULTI_TOUCHING,//多指触摸中 } /** * 手指触摸位置 */ public enum TouchPosition { EDGE_LT,//左上角 EDGE_RT,//右上角 EDGE_LB,//左下角 EDGE_RB,//右下角 EDGE_MOVE_IN,//裁剪框内部 EDGE_MOVE_OUT,//裁剪框外部 EDGE_NONE,//nothing } public CropImageView(Context context) { super(context); init(context); } public CropImageView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public CropImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } /** * 初始化 * * @param context */ private void init(Context context) { this.mContext = context; try { if (android.os.Build.VERSION.SDK_INT >= 11) { this.setLayerType(LAYER_TYPE_SOFTWARE, null); } } catch (Exception e) { e.printStackTrace(); } this.isFrist = true; mFloatDrawable = new FloatDrawable(context); dimenUtil = new DimenUtil(mContext); cropWidth = dimenUtil.getScreenWidth(); cropHeight = dimenUtil.getScreenHeight(); } /** * 设置被裁剪样本 * * @param mDrawable * @param cropWidth * @param cropHeight */ public void setDrawable(Drawable mDrawable, int cropWidth, int cropHeight) { this.cropWidth = cropWidth; this.cropHeight = cropHeight; this.mDrawable = mDrawable; invalidate(); } /** * 设置被裁剪样本 * * @param mDrawable */ public void setDrawable(Drawable mDrawable) { this.mDrawable = mDrawable; invalidate(); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getPointerCount() > 1) { switch (touchStatus) { case STATUS_SINGLE: touchStatus = TouchStatus.STATUS_MULTI_START; break; case STATUS_MULTI_START: touchStatus = TouchStatus.STATUS_MULTI_TOUCHING; break; } } else { switch (touchStatus) { case STATUS_MULTI_TOUCHING: case STATUS_MULTI_START: mX_1 = event.getX(); mY_1 = event.getY(); break; } touchStatus = TouchStatus.STATUS_SINGLE; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mX_1 = event.getX(); mY_1 = event.getY(); touchPosition = getTouchPosition(mX_1, mY_1); isTouchInSquare = mDrawableFloat.contains((int) event.getX(), (int) event.getY()); break; case MotionEvent.ACTION_UP: checkBounds(); break; case MotionEvent.ACTION_POINTER_UP: touchPosition = TouchPosition.EDGE_NONE; break; case MotionEvent.ACTION_MOVE: switch (touchStatus) { case STATUS_MULTI_TOUCHING: //多指触摸中... break; case STATUS_SINGLE: int dx = (int) (event.getX() - mX_1); int dy = (int) (event.getY() - mY_1); mX_1 = event.getX(); mY_1 = event.getY(); // 根據得到的那一个角,并且变换Rect if (!(dx == 0 && dy == 0)) { switch (touchPosition) { case EDGE_LT: mDrawableFloat.set(mDrawableFloat.left + dx, mDrawableFloat.top + dy, mDrawableFloat.right, mDrawableFloat.bottom); break; case EDGE_RT: mDrawableFloat.set(mDrawableFloat.left, mDrawableFloat.top + dy, mDrawableFloat.right + dx, mDrawableFloat.bottom); break; case EDGE_LB: mDrawableFloat.set(mDrawableFloat.left + dx, mDrawableFloat.top, mDrawableFloat.right, mDrawableFloat.bottom + dy); break; case EDGE_RB: mDrawableFloat.set(mDrawableFloat.left, mDrawableFloat.top, mDrawableFloat.right + dx, mDrawableFloat.bottom + dy); break; case EDGE_MOVE_IN: if (isTouchInSquare) { mDrawableFloat.offset(dx, dy); } break; case EDGE_MOVE_OUT: //这部分可以控制图片的缩放,位移 break; } mDrawableFloat.sort(); invalidate(); } break; } break; } return true; } /** * 根据初触摸点判断是触摸的Rect哪一个角 */ public TouchPosition getTouchPosition(float eventX, float eventY) { if (mFloatDrawable.getBounds().left <= eventX && eventX < (mFloatDrawable.getBounds().left + mFloatDrawable .getBorderWidth()) && mFloatDrawable.getBounds().top <= eventY && eventY < (mFloatDrawable.getBounds().top + mFloatDrawable .getBorderHeight())) { return TouchPosition.EDGE_LT; } else if ((mFloatDrawable.getBounds().right - mFloatDrawable .getBorderWidth()) <= eventX && eventX < mFloatDrawable.getBounds().right && mFloatDrawable.getBounds().top <= eventY && eventY < (mFloatDrawable.getBounds().top + mFloatDrawable .getBorderHeight())) { return TouchPosition.EDGE_RT; } else if (mFloatDrawable.getBounds().left <= eventX && eventX < (mFloatDrawable.getBounds().left + mFloatDrawable .getBorderWidth()) && (mFloatDrawable.getBounds().bottom - mFloatDrawable .getBorderHeight()) <= eventY && eventY < mFloatDrawable.getBounds().bottom) { return TouchPosition.EDGE_LB; } else if ((mFloatDrawable.getBounds().right - mFloatDrawable .getBorderWidth()) <= eventX && eventX < mFloatDrawable.getBounds().right && (mFloatDrawable.getBounds().bottom - mFloatDrawable .getBorderHeight()) <= eventY && eventY < mFloatDrawable.getBounds().bottom) { return TouchPosition.EDGE_RB; } else if (mFloatDrawable.getBounds().contains((int) eventX, (int) eventY)) { return TouchPosition.EDGE_MOVE_IN; } return TouchPosition.EDGE_MOVE_OUT; } @Override protected void onDraw(Canvas canvas) { //如果没有设置裁剪样本,则赋值一个空的图层 if (mDrawable == null) { mDrawable = new BitmapDrawable(mContext.getResources(), getEmptyBitmap()); } //设定 界限 规则 initBounds(); // 画图片 mDrawable.draw(canvas); //画裁剪框 drawCropUI(canvas); } /** * 绘制裁剪框样式 * * @param canvas */ private void drawCropUI(Canvas canvas) { if (!isCropEnable) { return; } canvas.save(); // 在画布上画浮层FloatDrawable,Region.Op.DIFFERENCE是表示Rect交集的补集 canvas.clipRect(mDrawableFloat, Region.Op.DIFFERENCE); // 在交集的补集上画上灰色用来区分 canvas.drawColor(Color.parseColor("#a0000000")); canvas.restore(); // 画浮层 mFloatDrawable.draw(canvas); } /** * 初始化 界限 参数,在onDraw方法中调用; * isFirst的目的是下面对mDrawableSrc和mDrawableFloat只初始化一次; * 之后的变化是根据touch事件来变化的,而不是每次执行重新对mDrawableSrc和mDrawableFloat进行设置 */ protected void initBounds() { if (isFrist) { oriRationWH = ((float) mDrawable.getIntrinsicWidth()) / ((float) mDrawable.getIntrinsicHeight()); final float scale = mContext.getResources().getDisplayMetrics().density; int w = Math.min(getWidth(), (int) (mDrawable.getIntrinsicWidth() * scale + 0.5f)); int h = (int) (w / oriRationWH); int left = (getWidth() - w) / 2; int top = (getHeight() - h) / 2; int right = left + w; int bottom = top + h; mDrawableSrc.set(left, top, right, bottom); mDrawableDst.set(mDrawableSrc); if (cropWidth > getWidth()) { cropWidth = getWidth(); cropHeight = cropHeight * cropWidth / cropWidth; } if (cropHeight > getHeight()) { cropHeight = getHeight(); cropWidth = cropWidth * cropHeight / cropHeight; } int floatLeft = (getWidth() - cropWidth) / 2; int floatTop = (getHeight() - cropHeight) / 2; mDrawableFloat.set(floatLeft, floatTop, floatLeft + cropWidth, floatTop + cropHeight); isFrist = false; } mDrawable.setBounds(mDrawableDst); mFloatDrawable.setBounds(mDrawableFloat); } /** * 在up事件中调用了该方法,目的是检查是否把浮层拖出了屏幕 */ protected void checkBounds() { int newLeft = mDrawableFloat.left; int newTop = mDrawableFloat.top; boolean isChange = false; if (mDrawableFloat.left < getLeft()) { newLeft = getLeft(); isChange = true; } if (mDrawableFloat.top < getTop()) { newTop = getTop(); isChange = true; } if (mDrawableFloat.right > getRight()) { newLeft = getRight() - mDrawableFloat.width(); isChange = true; } if (mDrawableFloat.bottom > getBottom()) { newTop = getBottom() - mDrawableFloat.height(); isChange = true; } mDrawableFloat.offsetTo(newLeft, newTop); if (isChange) { invalidate(); } } /** * 进行图片的裁剪,所谓的裁剪就是根据Drawable的新的坐标在画布上创建一张新的图片 */ public Bitmap getCropImage() { Bitmap result = null; if (!isCropEnable) { return result; } Bitmap tmpBitmap = getEmptyBitmap(); Canvas canvas = new Canvas(tmpBitmap); mDrawable.draw(canvas); result = Bitmap.createBitmap(tmpBitmap, mDrawableFloat.left, mDrawableFloat.top, mDrawableFloat.width(), mDrawableFloat.height()); recycle(tmpBitmap); return result; } private void recycle(Bitmap bitmap) { try { if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); System.gc(); } } catch (Exception var2) { var2.printStackTrace(); } } private Bitmap getEmptyBitmap() { return Bitmap.createBitmap(dimenUtil.getScreenWidth(), dimenUtil.getScreenHeight(), Bitmap.Config.RGB_565); }}
以上,类中用到的工具类:
import android.content.Context;import android.view.View;/** * Created by hmy */public class DimenUtil { private Context mContext; private float density = -1.0F; private int widthPixels = -1; private int heightPixels = -1; public DimenUtil(Context context) { this.mContext = context; } public float getDensity() { if (density <= 0.0F) { density = mContext.getResources().getDisplayMetrics().density; } return density; } public int dip2px(float dpValue) { return (int) (dpValue * getDensity() + 0.5F); } public int px2dip(float pxValue) { return (int) (pxValue / getDensity() + 0.5F); } public int getScreenWidth() { if (widthPixels <= 0) { widthPixels = mContext.getResources().getDisplayMetrics().widthPixels; } return widthPixels; } public int getScreenHeight() { if (heightPixels <= 0) { heightPixels = mContext.getResources().getDisplayMetrics().heightPixels; } return heightPixels; }}
还需要把裁剪框封装到另一个控件中,使用的时候将下面的控件作为根布局,调用相关方法就可以截屏其包含的view:import android.content.Context;import android.graphics.Bitmap;import android.graphics.drawable.BitmapDrawable;import android.util.AttributeSet;import android.view.View;import android.view.ViewTreeObserver;import android.widget.FrameLayout;/** * Created by hmy */public class ScreenShotView extends FrameLayout { private Context mContext; private CropImageView mCropIv; private int mWidth = 0; private int mHeight = 0; public ScreenShotView(Context context) { super(context); init(context); } public ScreenShotView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public ScreenShotView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { this.mContext = context; mCropIv = new CropImageView(mContext); } @Override protected void onFinishInflate() { super.onFinishInflate(); checkChildView(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); this.mWidth = this.getWidth(); this.mHeight = this.getHeight(); } /** * 检查子view */ private void checkChildView() { int count = this.getChildCount(); if (count != 1) { throw new RuntimeException("ScreenShotView can only have one child view!"); } else { this.addView(mCropIv); initScreenView(); } } /** * 初始化截屏view */ private void initScreenView() { final View screenView = this.getChildAt(0); screenView.buildDrawingCache(); // 允许当前窗口保存缓存信息 screenView.setDrawingCacheEnabled(true); //view加载完成时回调 screenView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { try { //获取bitmap Bitmap bmp = Bitmap.createBitmap(screenView.getDrawingCache(), 0, 0, mWidth, mHeight); // 销毁缓存信息 screenView.destroyDrawingCache(); mCropIv.setDrawable(new BitmapDrawable(mContext.getResources(), bmp)); } catch (Exception e) { e.printStackTrace(); } } }); } /** * 获取截取框内的图片 * * @return */ public Bitmap getCropImage() { return mCropIv.getCropImage(); } public void setCropEnable(boolean enable) { mCropIv.setCropEnable(enable); }}
使用方法:<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.hmy.android.allforme.view.ScreenShotView android:id="@+id/main_crop" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@mipmap/bj" /> </com.hmy.android.allforme.view.ScreenShotView> <ImageView android:id="@+id/main_iv" android:layout_width="100dp" android:layout_height="100dp" android:layout_alignParentRight="true" android:background="#afff" android:src="@mipmap/groundoverlay" /></RelativeLayout>
import android.app.Activity;import android.graphics.Bitmap;import android.os.Bundle;import android.view.View;import android.widget.ImageView;import com.hmy.android.allforme.R;import com.hmy.android.allforme.view.ScreenShotView;public class MainActivity extends Activity { private ScreenShotView imageView; private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = (ScreenShotView) findViewById(R.id.main_crop); iv = (ImageView) findViewById(R.id.main_iv); iv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Bitmap mBitmap = imageView.getCropImage(); iv.setImageBitmap(mBitmap); } }); }}
0 0
- 自定义控件-截屏当前界面
- 控件右滑退出当前界面
- 自定义组合控件---设置界面条目控件
- Qt 界面使用自定义控件 "提升为"
- Android 自定义控件 GuideView 引导界面
- 用户自定义控件 界面 不显示问题
- Qt 界面使用自定义控件 "提升为"
- 自定义控件之DragLayout仿QQ界面
- Android DIY(自定义) UI(控件,界面)
- 自定义控件之模仿W8界面
- 抓取当前界面上任意控件图像的C#代码
- DotNet(C#)自定义控件之界面编程(一)
- Launcher-自定义实现类似android主界面的滑屏换屏控件
- 自定义实现类似android主界面的滑屏换屏控件
- 自定义实现类似android主界面的滑屏换屏控件
- VC++界面编程之--自定义标签控件(CStatic)皮肤
- 在对话框程序中使用自定义控件-XT界面库
- 【Android界面实现】自定义音量调节控件的实现
- 创建你的第一款Phaser游戏
- socket异步编程--libevent的使用
- 用户空间与内核的交互---IOCTL
- Chrome浏览器下小于12号字的解决方案
- 程序员相关网站收集
- 自定义控件-截屏当前界面
- POJ 1064 Cable master (二分)
- Gridview 点击修改布局
- 机器学习-车牌识别框架学习
- android 完美隐藏软键盘
- IOCTL函数用法
- Caffe学习笔记10:图像数据生成caffe需要的(laveldb和lmdb)数据文件
- java生成图片验证码
- 密码提示语