Android实现bitmap指定区域滑动截取功能

突然不知道什么心态,说要做这个,网上找了半天没找到合适的,就自己做了一个。

先上效果图:

透明区域为将要截取的区域,其他阴影部位为舍弃区域

图片资源我写死储存在了raw中,有需要可以自己写获取bitmap。

界面layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.admin.myapplication.MainActivity">
  <com.admin.myapplication.ScreenShotView
    android:id="@+id/screenShotView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
  <LinearLayout
    android:id="@+id/title"
    android:layout_width="match_parent"
    android:layout_height="30dp"
    android:background="#000000">
    <TextView
      android:layout_width="match_parent"
      android:layout_height="20dp"
      android:layout_gravity="center"
      android:gravity="center"
      android:text="选择要截取区域"/>
  </LinearLayout>
  <LinearLayout
    android:id="@+id/bottom"
    android:layout_width="match_parent"
    android:layout_height="70dp"
    android:layout_alignParentBottom="true"
    android:background="#000000"
    android:orientation="horizontal">
    <TextView
      android:id="@+id/cancel_btn"
      android:text="取消"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_weight="1"
      android:layout_gravity="center_vertical"
      android:gravity="center"/>
    <TextView
      android:id="@+id/certain_btn"
      android:text="确定"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_weight="1"
      android:layout_gravity="center_vertical"
      android:gravity="center"/>
    <TextView
      android:id="@+id/restart_btn"
      android:text="重试"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_weight="1"
      android:layout_gravity="center_vertical"
      android:gravity="center"/>
  </LinearLayout>

</RelativeLayout>

ScreenShotView为自定义View用来显示bitmap,以及滑动截图,其中Dot类用来储存坐标点的x,y值。

public class ScreenShotView extends View {
  private Dot startDot;
  private Dot endDot;
  private Bitmap mBitmap;
  private Bitmap ocrBitmap;
  private int screenHeight;
  private int screenWidth;
  private Dot leftTopDot;
  private Dot rightBottomDot;
  private Paint paintShadow;
  int shadow = 0xaa000000;
  int clear = 0x0000000;

  public ScreenShotView(Context context) {
    super(context);
    startDot = new Dot();
    endDot = new Dot();
    leftTopDot = new Dot();
    rightBottomDot = new Dot();
  }

  public ScreenShotView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    startDot = new Dot();
    endDot = new Dot();
    leftTopDot = new Dot();
    rightBottomDot = new Dot();
  }

  public ScreenShotView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    startDot = new Dot();
    endDot = new Dot();
    leftTopDot = new Dot();
    rightBottomDot = new Dot();
  }

  public void setBitmap(Bitmap bitmap, int screenHeight, int screenWidth) {
    mBitmap = bitmap;
    this.screenHeight = screenHeight;
    this.screenWidth = screenWidth;
    changeBitmapSize();
    invalidate();
  }

  public void restart(){
    startDot = new Dot();
    endDot = new Dot();
    leftTopDot = new Dot();
    rightBottomDot = new Dot();
    invalidate();
  }
  /**
  *将将要显示的bitmap进行变形,使其铺满屏幕
  *
  */
  private void changeBitmapSize() {
    int width = mBitmap.getWidth();
    int height = mBitmap.getHeight();
    float scaleWidth = ((float) screenWidth) / width;
    float scaleHeight = ((float) screenHeight) / height;
    Matrix matrix = new Matrix();
    matrix.postScale(scaleWidth, scaleHeight);
    mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    getLeftTopDot();
    getRightBottomDot();
    drawBitmap(canvas);
    drawArea(canvas);
    drawShadowTop(canvas);
    drawShadowLeft(canvas);
    drawShadowRight(canvas);
    drawShadowBottom(canvas);
  }

  /**
  *绘制阴影
  *
  */
  private void drawShadowBottom(Canvas canvas) {
    paintShadow = new Paint();
    paintShadow.setColor(shadow);
    canvas.drawRect(0, rightBottomDot.getY(), screenWidth, screenHeight, paintShadow);
  }

  private void drawShadowRight(Canvas canvas) {
    paintShadow = new Paint();
    paintShadow.setColor(shadow);
    canvas.drawRect(rightBottomDot.getX(), leftTopDot.getY(), screenWidth, rightBottomDot.getY(), paintShadow);
  }

  private void drawShadowLeft(Canvas canvas) {
    paintShadow = new Paint();
    paintShadow.setColor(shadow);
    canvas.drawRect(0, leftTopDot.getY(), leftTopDot.getX(), rightBottomDot.getY(), paintShadow);
  }

  private void drawShadowTop(Canvas canvas) {
    paintShadow = new Paint();
    paintShadow.setColor(shadow);
    canvas.drawRect(0, 0, screenWidth, leftTopDot.getY(), paintShadow);
  }

  private void drawBitmap(Canvas canvas) {
    Paint paint = new Paint();
    canvas.drawBitmap(mBitmap, 0, 0, paint);
  }

  /**
   * 画出截图区域
   *
   * @param canvas
   */
  private void drawArea(Canvas canvas) {
    Paint paint = new Paint();
    paint.setColor(clear);
    canvas.drawRect(leftTopDot.getX(), leftTopDot.getY(), rightBottomDot.getX(), rightBottomDot.getY(), paint);
  }

  /**
   * 获取截图区域bitmap
   *
   * @return 截图
   */
  public Bitmap getBitmap() {
    if (mBitmap != null) {
      getLeftTopDot();
      getRightBottomDot();
      if (getBitmapOutWidth() > 0 && getBitmapOutHeight() > 0) {
        if(leftTopDot.getY()<0){
          leftTopDot.setY(0);
        }
        ocrBitmap = Bitmap.createBitmap(mBitmap, (int) leftTopDot.getX(), (int) leftTopDot.getY(), getBitmapOutWidth(), getBitmapOutHeight());
      }
    }
    return ocrBitmap;
  }

  /**
   * 获取截图区域宽度
   *
   * @return
   */
  private int getOutWidth() {
    return (int) (rightBottomDot.getX() - leftTopDot.getX());
  }

  /**
   * 获取截图区域高度
   *
   * @return
   */
  private int getOutHeight() {
    return (int) (rightBottomDot.getY() - leftTopDot.getY());
  }

  private int getBitmapOutWidth() {
    int bitmapOutWidth;
    int scale = getOutWidth() * mBitmap.getWidth();
    bitmapOutWidth = scale / screenWidth;
    return bitmapOutWidth;
  }

  private int getBitmapOutHeight() {
    int bitmapOutHeight;
    int scale = getOutHeight() * mBitmap.getHeight();
    bitmapOutHeight = scale / screenHeight;
    return bitmapOutHeight;
  }

  private void getLeftTopDot() {
    if (endDot.getX() > startDot.getX()) {
      leftTopDot.setX(startDot.getX());
    } else {
      leftTopDot.setX(endDot.getX());
    }
    if (endDot.getY() > startDot.getY()) {
      leftTopDot.setY(startDot.getY());
    } else {
      leftTopDot.setY(endDot.getY());
    }
  }

  private void getRightBottomDot() {
    if (startDot.getX() > endDot.getX()) {
      rightBottomDot.setX(startDot.getX());
    } else {
      rightBottomDot.setX(endDot.getX());
    }
    if (startDot.getY() > endDot.getY()) {
      rightBottomDot.setY(startDot.getY());
    } else {
      rightBottomDot.setY(endDot.getY());
    }

  }

  public Dot getStartDot() {
    return startDot;
  }

  public void setStartDot(Dot startDot) {
    this.startDot = startDot;
  }

  public Dot getEndDot() {
    return endDot;
  }

  public void setEndDot(Dot endDot) {
    this.endDot = endDot;
  }

}

MainActivity中完成对点击滑动的监控,通过坐标点的方式获得需要绘制的矩形位置和形状。

public class MainActivity extends AppCompatActivity implements View.OnTouchListener, View.OnClickListener {
  private ScreenShotView screenShotView;
  private Bitmap bmp;
  private Bitmap ocrBitmap;
  private TextView certainBtn;
  private TextView cancelBtn;
  private TextView restartBtn;
  private int screenWidth;
  private int screenHeight;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    screenShotView = (ScreenShotView) findViewById(R.id.screenShotView);
    cancelBtn = (TextView) findViewById(R.id.cancel_btn);
    cancelBtn.setOnClickListener(this);
    certainBtn = (TextView) findViewById(R.id.certain_btn);
    certainBtn.setOnClickListener(this);
    restartBtn = (TextView)findViewById(R.id.restart_btn);
    restartBtn.setOnClickListener(this);
    DisplayMetrics dm = new DisplayMetrics();
    //获取屏幕信息
    getWindowManager().getDefaultDisplay().getMetrics(dm);
    screenWidth = dm.widthPixels;
    screenHeight = dm.heightPixels;
    Resources r = this.getResources();
    InputStream is = r.openRawResource(R.raw.bg);
    BitmapDrawable bmpDraw = new BitmapDrawable(is);
    bmp = bmpDraw.getBitmap();
    screenShotView.setBitmap(bmp, screenHeight, screenWidth);
    screenShotView.setOnTouchListener(this);
  }

  @Override
  public boolean onTouch(View view, MotionEvent motionEvent) {
    switch (motionEvent.getAction()) {
      case MotionEvent.ACTION_DOWN:
        screenShotView.setStartDot(new Dot(motionEvent.getX(), motionEvent.getY()));
        break;
      case MotionEvent.ACTION_MOVE:
        screenShotView.setEndDot(new Dot(motionEvent.getX(), motionEvent.getY()));
        screenShotView.setBitmap(bmp, screenHeight, screenWidth);
        break;
      case MotionEvent.ACTION_UP:
        ocrBitmap = screenShotView.getBitmap();
        break;
    }
    return true;
  }

  @Override
  public void onClick(View view) {
    switch (view.getId()) {
      case R.id.cancel_btn:
        finish();
        break;
      case R.id.certain_btn:
        if (ocrBitmap != null) {
          BitmapUtil.getInstance().setImageBitmap(ocrBitmap);
          Intent intent = new Intent(MainActivity.this, Main2Activity.class);
          startActivity(intent);
        }else{
          Toast.makeText(MainActivity.this,"请选择截取区域",Toast.LENGTH_SHORT).show();
        }
        break;
      case R.id.restart_btn:
        screenShotView.restart();
        break;
    }
  }

  @Override
  protected void onResume() {
    super.onResume();
    screenShotView.restart();
  }

  @Override
  protected void onRestart() {
    super.onRestart();
    screenShotView.restart();
  }
}

运用了单例模式用来存储截取出来的bitmap,方便跳转时调用,不需要自己再写类,点击确定后,会将区域中的bitmap提取并存储在单例中,在下一个页面再调用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android中截取当前屏幕图片的实例代码

    复制代码 代码如下: /**     * 获取和保存当前屏幕的截图     */    private void GetandSaveCurrentImage()      {          //1.构建Bitmap          WindowManager windowManager = getWindowManager();          Display display = windowManager.getDefaultDisplay();          int w = d

  • android 手机截取长屏实例代码

    最近项目遇到一个需求:把当前页面保存到手机相册.想了想 我还不会呢,就百度了下大神的足迹,踏着大神的足迹,一路向前.废话不说,记录下,后期学习. public class ScreenUtils { /** * 截取scrollview的屏幕 * @param scrollView * @return */ public static Bitmap getBitmapByView(ScrollView scrollView) { int h = 0; Bitmap bitmap = null;

  • 解析Android截取手机屏幕两种实现方案

    最近在开发的过程中,遇到了一个需要截取屏幕保存为图片的需求,具体为截取webview的视图保存图片. 方法1:首先想到的思路是利用SDK提供的View.getDrawingCache()方法: public void printScreen(View view) { String imgPath = "/sdcard/test.png"; view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bitmap

  • Android 截取手机屏幕两种实现方法

    Android 截取手机屏幕两种实现方法 最近在开发的过程中,遇到了一个需要截取屏幕保存为图片的需求,具体为截取webview的视图保存图片. 方法1:首先想到的思路是利用SDK提供的View.getDrawingCache()方法: public void printScreen(View view) { String imgPath = "/sdcard/test.png"; view.setDrawingCacheEnabled(true); view.buildDrawingC

  • Android个人中心的头像上传,图片编码及截取实例

    首先需要有网络权限,然后我们这里匹配的网络请求是之前封装好的Okhttp. 非常的简单方便,直接复制进去,依赖一下包,然后调用方法即可. 这里是把图片转换成Base64.decode(imageString, Base64.DEFAULT); 转成Base64编码上传.具体内容也不少,需要完全整明白,还是要花点时间慢慢看的. 先看看简单的效果图: 那么万事具备,只欠东风了.直接上代码: public class MainActivity extends AppCompatActivity imp

  • Android实现拍照截取和相册图片截取

    关于拍照截取和相册截取,看了网上很多资料,自己整理了一份比较详细的,供有需要的人参考 1  拍照 原理就是通过intent调用系统的相机,拍完照在回调进行操作,成功获取到拍完照的图片根据uri调用系统的裁剪页面,裁剪完也是在回调中进行处理,显示在页面的imageview中. 2  相册选取图片 原理也是通过intent打开系统的图片,用户选择完成以后在回调中根据图片的uri调用系统的裁剪页面,同上. 首先,定义几个常量 public static final int TAKE_PHOTO = 1

  • Android 仿QQ头像自定义截取功能

    看了Android版QQ的自定义头像功能,决定自己实现,随便熟悉下android绘制和图片处理这一块的知识. 先看看效果: 思路分析: 这个效果可以用两个View来完成,上层View是一个遮盖物,绘制半透明的颜色,中间挖了一个圆:下层的View用来显示图片,具备移动和缩放的功能,并且能截取某区域内的图片. 涉及到的知识点: 1.Matrix,图片的移动和缩放 2.Paint的setXfermode方法 3.图片放大移动后,截取一部分 编码实现: 自定义三个View: 1.下层View:ClipP

  • Android截取视频帧并转化为Bitmap示例

    MainActivity如下: 复制代码 代码如下: package cn.testmediametadataretriever; import java.io.File; import java.io.FileOutputStream; import android.media.MediaMetadataRetriever; import android.os.Bundle; import android.os.Environment; import android.app.Activity;

  • Android开发获取短信的内容并截取短信

    1.首先我们要写一个广播接收器,当我们的手机收到短信时,系统会自动发送一个广播,我们只需要接收到这条广播就可以了 2.在广播里面,我们重写的onReceive()方法,通过里面的Intent写到的Bundle就可以拿到短信的内容, 3.清单文件里面我们必须要添加权限,否则无法接收到. 4.为了防止我们的广播接收不到,我们自己写的广播接收器的权限必须要大,以防万一,我设置了1000. 下面上代码,里面的注释也比较详细.. <?xml version="." encoding=&qu

  • Android实现bitmap指定区域滑动截取功能

    突然不知道什么心态,说要做这个,网上找了半天没找到合适的,就自己做了一个. 先上效果图: 透明区域为将要截取的区域,其他阴影部位为舍弃区域 图片资源我写死储存在了raw中,有需要可以自己写获取bitmap. 界面layout: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-au

  • Android开发之实现手势滑动的功能

    Android开发之实现手势滑动的功能 首先得Activity必须实现OnGestureListener接口,该接口提供了关于手势操作的一些方法, onDown方法:onDown是,一旦触摸屏按下,就马上产生onDown事件 public boolean onDown(MotionEvent e) { return false; } onFling方法:当手在屏幕上滑动但手未离开屏幕时触发 MotionEvent e1 手开始触碰屏幕的位置的MotionEvent对象 MotionEvent e

  • Android编程实现滑动按钮功能详解

    本文实例讲述了Android编程实现滑动按钮功能.分享给大家供大家参考,具体如下: 首先效果图: 然后是分别建立三个文件,第一个是main.class,第二个是SlipButton.class,第三个是 onchangeListener.class main.class import android.app.Activity; import android.os.Bundle; import android.widget.Toast; public class Main extends Acti

  • .NET SkiaSharp 生成二维码验证码及指定区域截取方法实现

    目录 正文 依赖的 Nuget 组件如下 正文 在最新版的 .NET 平台中,微软在逐步放弃 System.Drawing.Imaging ,给出的理由如下: System.Drawing命名空间对某些操作系统和应用程序类型有一些限制. 在Windows, System.Drawing 依赖于GDI+操作系统附带的本机库. 某些Windows SKUS Windows Server Core 或 Windows Nano)不包含此本机库作为 OS 的一部分. 如果使用此命名空间并且无法加载库,则

  • Android开发之拖动条/滑动条控件、星级评分控件功能的实例代码

    ProgressBar有2个子控件: SeekBar   拖动条控件 RatingBar   星级评分控件 1.拖动条控件 <SeekBar android:layout_width="300dp" android:layout_height="wrap_content" android:id="@+id/seekBar" android:min="0" android:max="100" andro

  • Android仿天猫横向滑动指示器功能的实现

    Android开发中会有很多很新奇的交互,比如天猫商城的首页头部的分类,使用的是GridLayoutManager+横向指示器实现的,效果如下图. 那对于这种效果要如何实现呢?最简单的方式就是使用RecyclerView+GridLayoutManager,我们知道RecyclerView可以实现九宫格,接下来就是通过RecyclerView控制指示器的显示位置,逻辑实现如下: 计算出RecyclerView划出屏幕的距离w1和剩余宽度w2的比例y,y = w1 / (总宽度w3 - 可使视区域

  • Android编程实现的首页左右滑动切换功能示例

    本文实例讲述了Android编程实现的首页左右滑动切换功能.分享给大家供大家参考,具体如下: 很多软件会选择左右滑动的主界面,实现方式也很多,这里的仅供参考,勿喷. 不多说什么了,相信大家看看代码就明白,自己也不善言辞,望大家谅解. 自定义接口,监听滑动翻页事件: /** 滑动后翻页事件 */ public interface OnViewChangedListener { public void OnViewChanged(int viewId); } 滑动翻页view(滑动翻页不是很灵敏):

  • Android开发中滑动分页功能实例详解

    本文实例讲述了Android开发中滑动分页功能.分享给大家供大家参考,具体如下: android UI 往右滑动,滑动到最后一页就自动加载数据并显示 如图: Java代码: package cn.anycall.ju; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import andro

  • Android开发中RecyclerView模仿探探左右滑动布局功能

    我在此基础上优化了部分代码, 添加了滑动回调, 可自定义性更强. 并且添加了点击按钮左右滑动的功能. 据说无图都不敢发文章了. 看图: 1:这种功能, 首先需要自己管理布局 继承 RecyclerView.LayoutManager , 显示自己管理布局, 比如最多显示4个view, 并且都是居中显示. 底部的View还需要进行缩放,平移操作. public class OverLayCardLayoutManager extends RecyclerView.LayoutManager { p

随机推荐