Android实现裁剪

2023-11-19

Android自定义View实现图片缩放旋转移动裁剪 - 灰信网(软件开发博客聚合) (freesion.com)

@SuppressLint("AppCompatCustomView")
public class CorpToView extends ImageView {
    /**
     * 按下的点不在裁剪框上
     */
    private static final int POS_OUT_OF_CLIP_RECT = -1;
    private static final int POS_TOP_LEFT = 0;
    private static final int POS_TOP_RIGHT = 1;
    private static final int POS_BOTTOM_LEFT = 2;
    private static final int POS_BOTTOM_RIGHT = 3;
    private static final int POS_TOP = 4;
    private static final int POS_BOTTOM = 5;
    private static final int POS_LEFT = 6;
    private static final int POS_RIGHT = 7;

    /**
     * 拖拽的是剪裁框里面
     */
    private static final int POS_CENTER = 8;
    private static final float BORDER_CORNER_LENGTH = 30f;
    private static final float TOUCH_FIELD = 10f;

    /**
     * 当前裁剪框是拖拽还是缩放
     */
    private int mood = NONE;

    /**
     * 裁剪框既不拖拽也不缩放
     */
    private static final int NONE = 0;
    /**
     * 拖拽裁剪框
     */
    private static final int DRAG = 1;
    /**
     * 缩放裁剪框
     */
    private static final int ZOOM = 2;

    private Matrix matrix = new Matrix();
    private Matrix currentMatrix = new Matrix();

    /**
     * 手指最开始按下时的点的坐标
     */
    private PointF startPoint = new PointF();
    private PointF lastPoint = new PointF();

    private PointF centerPointForZoom;

    private float twoFingerDistanceBeforeZoom;

    /**
     * 放置图片的容器View
     */
    private RectF viewRectF;

    /**
     * 要裁剪的原图的路径
     */
    private String mImagePath;

    /**
     * 存放图片的Bitmap,后面所有的图片的操作,都市通过这个对象
     */
    private Bitmap mBmpToCrop;

    /**
     * 绘制图片上面蒙版的画笔
     */
    private Paint maskLayoutPaint;

    /**
     * 裁剪框位置
     */
    private RectF clipRect;
    
    /**
     * 九宫图裁剪区外边框
     */
    private Paint clipRectBorderPaint;

    /**
     * 四个角小圆圈
     */
    private Paint clipRectCornerPaint;

    /**
     *裁剪框4条边框画笔
     */
    private Paint clipRectGuidelinePaint;

    private int touchPosition;

    /**
     * 是否点击了裁剪按钮
     */
    private boolean isClip = false;

    /**
     * 只画一次,初始化view中图片,裁剪框等的位置
     */
    private boolean isFirstDraw = true;

    public CorpToView(Context context) {
        super(context);
        init(context);
    }

    public CorpToView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        Paint mBmpPaint;
        mBmpPaint = new Paint();
        // 防止边缘的锯齿
        mBmpPaint.setAntiAlias(true);
        // 对位图进行滤波处理
        mBmpPaint.setFilterBitmap(true);

        // 初始化裁剪框边框的画笔
        clipRectBorderPaint = new Paint();
        clipRectBorderPaint.setStyle(Style.STROKE);
        clipRectBorderPaint.setColor(Color.parseColor("#AAFFFFFF"));//#AAFFFFFF
        clipRectBorderPaint.setStrokeWidth(6f);

        // 初始化裁剪框辅助线的画笔
        clipRectGuidelinePaint = new Paint();
        clipRectGuidelinePaint.setColor(Color.parseColor("#AAFFFFFF"));//#AAFFFFFF
        clipRectGuidelinePaint.setStrokeWidth(1f);

        // 初始化裁剪框边框四个角圆圈的画笔
        clipRectCornerPaint = new Paint();
        clipRectCornerPaint.setColor(Color.parseColor("#AAFFFFFF"));

        // 初始化整个View遮罩层的画笔
        maskLayoutPaint = new Paint();
        maskLayoutPaint.setColor(Color.parseColor("#AAFFFFFF"));
        maskLayoutPaint.setAlpha(150);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 获取自定义view宽高,设置第一次绘图是裁剪框和图片在中心显示。
        // 如果是通过intent打开相册选择图片,这个地方需要自行修改,就不能使用这个判断了,需要把下面的几个方法放到其他的位置
        if(isFirstDraw) {
            setViewRectF();
            setClipRectDefaultPosition();
            setPictureDefaultPosition();
            isFirstDraw = false;
        }

        // 有图片才画
        if (mImagePath != null) {
            // 画原图
            canvas.drawBitmap(mBmpToCrop, matrix, null);
            if(!isClip) {
                // 画裁剪框
                canvas.drawRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, clipRectBorderPaint);
                // 画裁剪框4个角上的圆圈
                draw4RoundCorner(canvas);
                // 画裁剪框的辅助线
                drawGuideLines(canvas);
                // 画遮罩层
                drawMaskLayer(canvas);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction() & MotionEvent.ACTION_MASK){
            // 手指按下
            case MotionEvent.ACTION_DOWN:
                mood = DRAG;

                // 手指按下的点
                startPoint.set(event.getX(), event.getY());
                lastPoint.set(event.getX(),event.getY());

                getParent().requestDisallowInterceptTouchEvent(true);
                touchPosition = detectTouchPosition(event.getX(), event.getY());

                if(touchPosition == POS_OUT_OF_CLIP_RECT ) {
                    currentMatrix.set(matrix);
                }

                break;
            // 手指进行移动
            case MotionEvent.ACTION_MOVE :
                if (mood == DRAG){
                    if(touchPosition == POS_OUT_OF_CLIP_RECT) {
                        moveImage(event);
                    } else {
                        moveOrChangeClipRect(event);
                    }
                }else if (mood == ZOOM){
                    float twoFingerDistanceAfterZoom = calculateFingersSlideDistance(event);
                    if (twoFingerDistanceAfterZoom > 10f) {
                        // 缩放比例
                        float scale = twoFingerDistanceAfterZoom / twoFingerDistanceBeforeZoom;

                        matrix.set(currentMatrix);
                        matrix.postScale(scale, scale, centerPointForZoom.x, centerPointForZoom.y);
                    }
                }

                lastPoint.set(event.getX(),event.getY());
                break;
            // 手指抬起
            case MotionEvent.ACTION_UP:
                mood = NONE;
                break;
            case MotionEvent.ACTION_POINTER_UP:
                mood = NONE;
                break;
            // 屏幕上已经有一根手指,再放下一根
            case MotionEvent.ACTION_POINTER_DOWN:
                mood = ZOOM;
                twoFingerDistanceBeforeZoom = calculateFingersSlideDistance(event);
                if (twoFingerDistanceBeforeZoom > 10f) {
                    centerPointForZoom = calculateCenterPointForZoom(event);
                    currentMatrix.set(matrix);
                }
                break;
        }
        // 调用 onDraw方法
        invalidate();
        // 这里一定要是return true 不然也是无效的
        return true;
    }

    /**
     * 在View中显示原图
     * @param picPath 原图的路径
     */
    public void showImage(String picPath) {
        this.mImagePath = picPath;
        mBmpToCrop = BitmapFactory.decodeFile(mImagePath);
        invalidate();
    }

    /**
     * 让图片旋转90度
     */
    public void rotate90(){
        matrix.preRotate(90,mBmpToCrop.getWidth()/2,mBmpToCrop.getHeight()/2);
        invalidate();
    }

    private void setViewRectF() {
        viewRectF = new RectF();
        viewRectF.left = 0;
        viewRectF.top = 0;
        viewRectF.right =  getWidth();
        viewRectF.bottom = getHeight();
    }

    /**
     * 设置裁剪框默认的大小和在view上的位置
     */
    private void setClipRectDefaultPosition() {
        // 裁剪框默任宽高
        final float CLIP_RECT_WIDTH = 200f;
        final float CLIP_RECT_HEIGHT = 200f;

        // 使裁剪框一开始出现在图片的中心位置
        clipRect = new RectF();
        clipRect.left = (viewRectF.width() - CLIP_RECT_WIDTH) / 2;
        clipRect.top = (viewRectF.height() - CLIP_RECT_HEIGHT) / 2;
        clipRect.right = clipRect.left + CLIP_RECT_WIDTH;;
        clipRect.bottom = clipRect.top + CLIP_RECT_HEIGHT;

    }
    /**
     * 显示原图时,设置图片显示在view中的位置
     */
    private void setPictureDefaultPosition () {
        float dx = 0;
        float dy = 0;

        if(mBmpToCrop.getWidth() < viewRectF.width()) {
            dx = (viewRectF.width() - mBmpToCrop.getWidth()) / 2;
        }

        if(mBmpToCrop.getHeight() < viewRectF.height()) {
            dy = (viewRectF.height() - mBmpToCrop.getHeight()) / 2;
        }

        // 平移缩放模式,相对于当前位置,移动多少距离
        matrix.postTranslate(dx,dy);

    }
    /**
     * 获取裁剪框区域的图片
     * @return
     */
    public Bitmap getClipRectImage() {
        isClip = true;
        destroyDrawingCache();
        setDrawingCacheEnabled(true);
        buildDrawingCache();
        Bitmap mBitmap  = getDrawingCache();
        isClip = false;
        return Bitmap.createBitmap(mBitmap, (int) clipRect.left, (int) clipRect.top, (int) clipRect.width(), (int) clipRect.height());
    }


    /**
     * 自测用,在自定义view中显示裁剪的图片,覆盖之前的图片。可以忽略此方法
     */
    public void showCilpRectImage() {

        isClip = true;
        destroyDrawingCache();
        setDrawingCacheEnabled(true);
        buildDrawingCache();
        Bitmap mBitmap  = getDrawingCache();

        mBmpToCrop =Bitmap.createBitmap(mBitmap, (int) clipRect.left, (int) clipRect.top, (int) clipRect.width(), (int) clipRect.height());
        matrix = new Matrix();
        isClip = false;
        invalidate();
    }

    /**
     * 拖拽图片是,移动图片
     * @param event
     */
    private void moveImage (MotionEvent event) {
        // 图片要移动的距离
        float dx = event.getX() - startPoint.x;
        float dy = event.getY() - startPoint.y;

        // 平移缩放模式,相对于当前位置,移动多少距离
        matrix.set(currentMatrix);
        matrix.postTranslate(dx,dy);
    }

    /**
     * 移动裁剪框或者改变裁剪框大小
     * @param event
     */
    private void moveOrChangeClipRect(MotionEvent event) {
        float deltaX = event.getX() - lastPoint.x;
        float deltaY = event.getY() - lastPoint.y;

        switch (touchPosition) {
            case POS_CENTER:
               moveWholeClipRect(deltaX,deltaY);
                break;
            case POS_TOP:
                changeClipRectTop(deltaY);
                break;
            case POS_BOTTOM:
                changeClipRectBottom(deltaY);
                break;
            case POS_LEFT:
                changeClipRectLeft(deltaX);
                break;
            case POS_RIGHT:
                changeClipRectRight(deltaX);
                break;
            case POS_TOP_LEFT:
                changeClipRectTop(deltaY);
                changeClipRectLeft(deltaX);
                break;
            case POS_TOP_RIGHT:
                changeClipRectTop(deltaY);
                changeClipRectRight(deltaX);
                break;
            case POS_BOTTOM_LEFT:
                changeClipRectBottom(deltaY);
                changeClipRectLeft(deltaX);
                break;
            case POS_BOTTOM_RIGHT:
                changeClipRectBottom(deltaY);
                changeClipRectRight(deltaX);
                break;
            default:

                break;
        }
    }

    /**
     * 获取缩放时的中心位置
     */
    private PointF calculateCenterPointForZoom(MotionEvent event) {
        float midx = event.getX(1) + event.getX(0);
        float midy = event.getY(1) + event.getY(0);
        return new PointF(midx/2,midy/2);
    }

    /**
     * 计算手指滑动距离
     * @param event
     * @return
     */
    private float calculateFingersSlideDistance(MotionEvent event) {
        float dx = event.getX(1) - event.getX(0);
        float dy = event.getY(1) - event.getY(0);
        return (float)Math.sqrt(dx * dx + dy * dy);
    }

    /**
     * 绘制剪切的框四周半透明的遮罩层
     * @param canvas
     */
    private void drawMaskLayer(Canvas canvas) {

        /*-
          -------------------------------------
          |              遮罩层top             |
          -------------------------------------
          |  遮  |                     |  遮   |
          |  罩  |                     |  罩   |
          |  层  |                     |  层   |
          | left |        可见层       | right |
          |      |                    |       |
          -------------------------------------
          |            遮罩层bottom            |
          -------------------------------------
         */

        PointF p1 = new PointF();
        PointF p2 = new PointF();

        // 上阴影
        p1.set(0,0);
        p2.set(viewRectF.width(),clipRect.top);
        canvas.drawRect(p1.x,p1.y,p2.x,p2.y, maskLayoutPaint);

        // 下阴影
        p1.set(0,clipRect.bottom);
        p2.set(viewRectF.width(),viewRectF.height());
        canvas.drawRect(p1.x,p1.y,p2.x,p2.y, maskLayoutPaint);

        // 左阴影
        p1.set(0,clipRect.top);
        p2.set(clipRect.left,clipRect.bottom);
        canvas.drawRect(p1.x,p1.y,p2.x,p2.y, maskLayoutPaint);

        //右阴影
        p1.set(clipRect.right,clipRect.top);
        p2.set(viewRectF.width(),clipRect.bottom);
        canvas.drawRect(p1.x,p1.y,p2.x,p2.y, maskLayoutPaint);
    }

    /**
     * 画裁剪区域中间的参考线
     * @param canvas
     */
    private void drawGuideLines(Canvas canvas) {
        // Draw vertical guidelines.
        final float oneThirdCropWidth = clipRect.width() / 3;

        final float x1 = clipRect.left + oneThirdCropWidth;
        canvas.drawLine(x1, clipRect.top, x1, clipRect.bottom, clipRectGuidelinePaint);
        final float x2 = clipRect.right - oneThirdCropWidth;
        canvas.drawLine(x2, clipRect.top, x2, clipRect.bottom, clipRectGuidelinePaint);

        // Draw horizontal guidelines.
        final float oneThirdCropHeight = clipRect.height() / 3;

        final float y1 = clipRect.top + oneThirdCropHeight;
        canvas.drawLine(clipRect.left, y1, clipRect.right, y1, clipRectGuidelinePaint);
        final float y2 = clipRect.bottom - oneThirdCropHeight;
        canvas.drawLine(clipRect.left, y2, clipRect.right, y2, clipRectGuidelinePaint);
    }

    /**
     * 裁剪框四个角的圆圈
     * @param canvas
     */
    private void draw4RoundCorner(Canvas canvas) {
        canvas.drawCircle(clipRect.left,clipRect.top,12,clipRectCornerPaint);
        canvas.drawCircle(clipRect.right,clipRect.top,12,clipRectCornerPaint);
        canvas.drawCircle(clipRect.left,clipRect.bottom,12,clipRectCornerPaint);
        canvas.drawCircle(clipRect.right,clipRect.bottom,12,clipRectCornerPaint);
    }

    /**
     * 检测按下触碰的点在裁剪框上的哪个位置上,或者没在裁剪框上
     * @param x
     * @param y
     * @return
     */
    private int detectTouchPosition(float x, float y) {
        if (x > clipRect.left + TOUCH_FIELD && x < clipRect.right - TOUCH_FIELD
                && y > clipRect.top + TOUCH_FIELD && y < clipRect.bottom - TOUCH_FIELD)
            return POS_CENTER;

        if (x > clipRect.left + BORDER_CORNER_LENGTH && x < clipRect.right - BORDER_CORNER_LENGTH) {
            if (y > clipRect.top - TOUCH_FIELD && y < clipRect.top + TOUCH_FIELD)
                return POS_TOP;
            if (y > clipRect.bottom - TOUCH_FIELD && y < clipRect.bottom + TOUCH_FIELD)
                return POS_BOTTOM;
        }

        if (y > clipRect.top + BORDER_CORNER_LENGTH && y < clipRect.bottom - BORDER_CORNER_LENGTH) {
            if (x > clipRect.left - TOUCH_FIELD && x < clipRect.left + TOUCH_FIELD)
                return POS_LEFT;
            if (x > clipRect.right - TOUCH_FIELD && x < clipRect.right + TOUCH_FIELD)
                return POS_RIGHT;
        }

        // 前面的逻辑已经排除掉了几种情况 所以后面的 ┏ ┓ ┗ ┛ 边角就按照所占区域的方形来判断就可以了
        if (x > clipRect.left - TOUCH_FIELD && x < clipRect.left + BORDER_CORNER_LENGTH) {
            if (y > clipRect.top - TOUCH_FIELD && y < clipRect.top + BORDER_CORNER_LENGTH)
                return POS_TOP_LEFT;
            if (y > clipRect.bottom - BORDER_CORNER_LENGTH && y < clipRect.bottom + TOUCH_FIELD)
                return POS_BOTTOM_LEFT;
        }

        if (x > clipRect.right - BORDER_CORNER_LENGTH && x < clipRect.right + TOUCH_FIELD) {
            if (y > clipRect.top - TOUCH_FIELD && y < clipRect.top + BORDER_CORNER_LENGTH)
                return POS_TOP_RIGHT;
            if (y > clipRect.bottom - BORDER_CORNER_LENGTH && y < clipRect.bottom + TOUCH_FIELD)
                return POS_BOTTOM_RIGHT;
        }

        return POS_OUT_OF_CLIP_RECT;
    }

    /**
     * 改变裁剪框左边框与view左边框的距离
     * @param delta
     */
    private void changeClipRectLeft(float delta) {
        clipRect.left += delta;
        preventClipRectLeftOverView();
    }

    /**
     * 不改变大小,移动裁剪框位置
     * @param deltaX
     * @param deltaY
     */
    private void moveWholeClipRect(float deltaX,float deltaY) {

        float width = clipRect.width();
        float height = clipRect.height();

        clipRect.left += deltaX;

        if (clipRect.left < viewRectF.left) {
            clipRect.left = viewRectF.left;
        }

        if (clipRect.left > viewRectF.right - clipRect.width()) {
            clipRect.left = viewRectF.right - clipRect.width();
        }

        clipRect.top += deltaY;
        if (clipRect.top < viewRectF.top) {
            clipRect.top = viewRectF.top;
        }

        if (clipRect.top > viewRectF.bottom - clipRect.height()) {
            clipRect.top = viewRectF.bottom - clipRect.height();
        }

        clipRect.right = clipRect.left + width;
        clipRect.bottom = clipRect.top + height;
    }

    /**
     * 改变裁剪框上边框与view上边框的距离
     * @param delta
     */
    private void changeClipRectTop(float delta) {
        clipRect.top += delta;
        preventClipRectTopOverView();
    }

    /**
     * 改变裁剪框右边框与view右边框的距离
     * @param delta
     */
    private void changeClipRectRight(float delta) {
        clipRect.right += delta;
        preventClipRectRightOverView();

    }

    /**
     * 改变裁剪框下边框与view下边框的距离
     * @param delta
     */
    private void changeClipRectBottom(float delta) {
        clipRect.bottom += delta;
        preventClipRectBottomOverView();
    }

    /**
     * 防止裁剪框左侧超出View
     */
    private void preventClipRectLeftOverView() {
        if (clipRect.left < viewRectF.left) {
            clipRect.left = viewRectF.left;
        }

        if (clipRect.width() < 2 * BORDER_CORNER_LENGTH) {
            clipRect.left = clipRect.right - 2 * BORDER_CORNER_LENGTH;
        }
    }

    /**
     * 防止裁剪框顶部超出View
     */
    private void preventClipRectTopOverView() {
        if (clipRect.top < viewRectF.top) {
            clipRect.top = viewRectF.top;
        }

        if (clipRect.height() < 2 * BORDER_CORNER_LENGTH) {
            clipRect.top = clipRect.bottom - 2 * BORDER_CORNER_LENGTH;
        }
    }

    /**
     * 防止裁剪框右侧超出View
     */
    private void preventClipRectRightOverView() {
        if (clipRect.right > viewRectF.right){
            clipRect.right = viewRectF.right;
        }

        if (clipRect.width() < 2 * BORDER_CORNER_LENGTH) {
            clipRect.right = clipRect.left + 2 * BORDER_CORNER_LENGTH;
        }
    }

    /**
     * 防止裁剪框底部超出View
     */
    private void preventClipRectBottomOverView() {
        if (clipRect.bottom > viewRectF.bottom) {
            clipRect.bottom = viewRectF.bottom;
        }

        if (clipRect.height() < 2 * BORDER_CORNER_LENGTH) {
            clipRect.bottom = clipRect.top + 2 * BORDER_CORNER_LENGTH;
        }
    }
}
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android实现裁剪 的相关文章

  • 如何防止我的 servlet 被其他网站调用

    好的 我有一个像这样的简单的 servlet public class SimpleServlet extends HttpServlet public void doPost HttpServletRequest req HttpServ
  • 覆盖乔达一周的第一天?

    是否有可能覆盖乔达弱的第一天sunday 因为 Joda 使用Monday作为一周的第一天 如果有办法的话 谁能解释一下 我在 SOF 中提到了以下主题 乔达时间 一周的第一天 https stackoverflow com questio
  • 基于磁盘的 HashMap [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Java 是否有 或者是否有可用的库 允许我拥有基于磁盘的 HashMap 它不需要是原子的或任何东西
  • java多线程中“私有最终对象”锁定有什么用?

    java多线程中 私有最终对象 锁定有什么用 据我的理解 我认为要使一个类成为线程安全的 我们应该使用内部锁定 将所有方法标记为同步并使用 this 将它们锁定在对象的监视器上 或者我们可以用方法中的私有最终对象锁替换类的 this 上标记
  • 将 glReadPixels 替换为 EGL_KHR_image_base 以加快像素复制速度

    我试图在 Android 本机进程中使用 EGL KHR image base 来替换 glReadPixels 因为它很慢 1280x800 RGBA 为 220ms 这是我到目前为止所拥有的 但我的它产生一个空缓冲区 只有零 uint8
  • Android 中 Bitmap 和 Drawable 有什么区别?

    我用谷歌搜索 但找不到任何文章来描述 Android 中 Bitmap 和 Drawable 之间的区别 位图是位图图像的表示 类似于 java awt Image Drawable 是 可以绘制的东西 的抽象 它可能是一个位图 包装为Bi
  • 如何更改Android软键盘中任意键的按键背景

    我想让键盘上的一些键与其他键不同 例如下图中的shift 删除 空格键 根据google的参考文档 我们可以通过使用 来改变按键的背景android keybackground drawable xxx in input xml 但它改变了
  • mysql 准备好的语句错误:MySQLSyntaxErrorException

    我使用准备好的语句编写了选择语句 每次尝试运行都会出现此错误 我如何克服这个错误 我的jdbc连接器是mysql connector java 5 1 13 bin jar 我的代码 public Main add ad to getAdD
  • Java泛型类型参数中的问号是什么意思? [复制]

    这个问题在这里已经有答案了 这是取自斯坦福解析器附带的一些示例的一小段代码 我已经用 Java 进行了大约 4 年的开发 但从未对这种风格的代码应该表示什么有非常深入的理解 List
  • 如何在flutter app android中添加Startapp广告?

    我想用其他广告更改 AdMob 广告 一些个人问题 如何在flutter app android中添加Startapp广告 有什么方法可以将启动广告添加到我的 flutter 应用程序 android 中 StartApp 现已更名为 St
  • Android 中应用程序在后台运行时如何显示闪屏?

    我的应用程序有一个启动屏幕 无法避免它 因为这是出于品牌原因 我想屏蔽用户界面并在后台显示启动屏幕 就像银行应用程序那样 我应该覆盖 MainActivity 中视图的 onPause 和 onResume 吗 显现
  • 如何使用Android Studio录制Android屏幕?

    我已经在 Mac 上的 Applications 文件夹中安装了 Android Studio 我认为 sdk 位于包内容中 但现在我想使用 AShot jar 录制屏幕以获取应用程序的演示视频 我必须放弃SDK的路径 当我给出我认为正确的
  • Android动态功能模块,找不到资源

    当下载的功能模块发布到 Play 商店时 我在启动活动时遇到问题 它总是在下载模块活动中的 setContentView 上崩溃 java lang RuntimeException Unable to start activity Com
  • Java无损保存原始JPEG

    如下所示 我有第一张图像是原始 JPEG 图像 第二张图像用于缓冲图像 然后使用保存http www lac inpe br JIPCookbook 6040 howto compressimages jsp http www lac in
  • 优雅地避免 Java 中的 NullPointerException

    考虑这一行 if object getAttribute someAttr equals true 显然这一行是一个潜在的错误 属性可能是null我们会得到一个NullPointerException 因此我们需要将其重构为以下两个选择之一
  • 当框架被拖动时,如何设置 JWindow 的位置位于文本字段下方?

    我正在制作一个自动完成项目 就像谷歌一样 我的框架中有一个 jtextfield 每当我在该字段中输入内容时 该文本字段下方就会出现一个 JWindow 并且该窗口来自另一个类 现在的问题是 每当我拖动框架时 如何使窗口始终出现在文本字段下
  • 如何使用 iBatis (myBatis) 的注释进行 IN 查询?

    我们只想在 MyBatis 中使用注释 我们确实在努力避免使用 xml 我们尝试使用 IN 子句 Select SELECT FROM blog WHERE id IN ids List
  • 片段已添加 IllegalStateException

    我在容器 Activity 上使用此方法来显示 BFrag public void showBFrag Start a new FragmentTransaction FragmentTransaction fragmentTransact
  • 如何在Android手机上而不是模拟器上运行或调试?

    Android 模拟器速度太慢 无法测试运行的应用程序 有没有办法使用 IDE 而不是模拟器在真实手机上调试 运行应用程序 通常 您可以在手机上打开 USB 调试 然后通过 USB 将其连接到 PC 然后 手机将以与模拟器相同的方式出现在
  • getApplicationDocumentsDirectory 在 flutter 桌面(Windows)上不起作用

    如何在 Windows 上的 flutter 桌面上保存和打开文件 getApplicationDocumentsDirectory 不适用于 Windows 应用程序的 flutter 桌面 Future

随机推荐

  • 查看解决inode使用率100%的问题

    今天登录后端服务器查看 发现程序报错日志中存在磁盘空间不足的情况 df h后发现磁盘空间充足 df ih发现 app分区inode使用率100 开始查找原因 进到 app 下 然后 for i in do echo i find i wc
  • hashMap常见的问题解答

    1 HashMap的数据结构 hashmap采取数组 链表的数据结构 在遇到哈希冲突的时候采用链表结构来解决哈希冲突 jdk1 8后分成了两种情况 bucket中元素个数大于8的时候 自动转换为红黑树的结构 目的是因为链表的查询速度比较慢
  • vue+element table 合并列

    vue element table 合并列
  • 【TCP/IP详解 卷一:协议】TCP的小结

    前言 TCP学习的综述 在学习TCP IP协议的大头 TCP协议 的过程中 遇到了很多机制和知识点 详解中更是用了足足8章的内容介绍它 TCP协议作为 应用层 和 网络层 中间的 传输层协议 既要为下面的网络层协议保证连接的可靠性 IP协议
  • 通过Jib将Springboot应用通过Docker部署

    一 安装Docker 1 更新Yum包 yum update 2 卸载旧版本 如果安装过旧版本的话 1 删除软件包 yum remove y docker docker client docker client latest docker
  • 【Espruino】NO.14 温湿度传感器DHT11

    http blog csdn net qwert1213131 article details 35828873 本文属于个人理解 能力有限 纰漏在所难免 还望指正 小鱼有点电
  • 环境变量是如何生效的——以Linux操作系统为例

    什么是环境变量 从我们学习Java开始 就经常接触一个东西 PATH 也叫环境变量 环境变量是操作系统提供给应用程序访问的简单 key value字符串 windows linux mac都有同样的概念 环境变量的作用 当我们拥有一个可执行
  • Git版本回退并强制推送到远端

    Git版本回退并强制推送到远端 本文参考廖雪峰的Git教程 前言 本文章解决问题的前提是本人不小心修改了本地代码仓库的最外层目录权限 不知道原权限是什么 导致本地git提示几十个文件被修改过 实际内容并未修改 可能是目录权限改变被git识别
  • C++ - 继承 一些 细节 - 组合 和 继承的区别

    前言 本篇博客基于 C 继承 chihiro1122的博客 CSDN博客 之上列出一些例子 如果有需要请看以上博客 继承的例子 例1 上述例子应该选择 C 首先不用说 p3肯定是指向 d 对象的开头的 p1 也是指向 d 对象的开头的 不同
  • 机器学习即服务:关于情感分析的10个应用场景和4个服务

    情感分析是什么 用户生成内容的爆炸式增长和档案材料的数字化创造了大量的数据集 其中包含了许多人对几乎每一个主题发表的观点 在某些情况下 该数据的生成是通过用户界面构造的 例如 在电子商务网站上处理客户评论相对容易 因为用户需要在产品评论的文
  • C++模板基础(六)

    类模板与成员函数模板 使用 template 关键字引入模板 template class B 类模板的声明与定义 翻译单元的一处定义原则 template
  • html5页面刷新时显示新数据,用ajax使网页不刷新就可以显示新数据

    用AjaxPro的 1 在引用中添加引用AjaxPro dll 我用的是这个 支持asp net 1 1 和asp net 2 0 2 web config中建立HttpHandler 3 新建一个类Demo 这个类里面提供了查询数据库和输
  • 怎么在html中复制粘贴图片,如何复制其他网页上的文章和图片

    首先 我们并不建议直接复制别人的内容 以免侵权 但是不排除在某些情况下 需要将其他网页上的内容完整的复制到你的网站中 比如 将自己的微博文章复制到自己的网站 大部分人都知道这个简单的方法 先选中目标文字按CTRL C快捷键 然后再网站后台文
  • AngularJS学习之全局API(应用程序编程接口)

    1 AngularJS全局API用于执行常见任务的Javascript函数集合 比较对象 迭代对象 转换对象 2 全局API函数使用angularJS对象进行访问 以下是通用API函数 angular lowercase 转换字符串为小写
  • Unity用Vuforia做AR实现脱卡效果

    有时在识别目标丢失后我们仍希望虚拟物体能够出现在摄像机前 或者到一个特定的位置 我们能对其进行操作 这就是脱卡功能 自带的脱卡功能应该是ExtendedTracking 允许模型在识别图丢失的时候还存在 位置不变 在丢失的时候的位置 这样也
  • 用Python实现火车票查询(含票价版)

    用Python实现火车票查询 含票价版 写在前面 网上关于用Python3编写火车查询脚本的版本众多 我在前人的基础上编写了自己的这个版本 我觉得的写的这个版本有以下几个特色 1 智能引导输入 我一直比较喜欢这种方式 如果直接做成GUI的图
  • 基于分位数回归的门控循环单元QRGRU时间序列区间预测。(主要应用于风速,负荷,功率)包含评价指标R2,MAE,MBE,区间覆盖率,区间平均宽度。

    清空环境变量 warning off 关闭报警信息 close all 关闭开启的图窗 clear 清空变量 clc 清空命令行 导入数据 时间序列的单列数据 result xlsread 数据集 xlsx 数据分析 num samples
  • Sublime Text配置anaconda环境

    Ref https blog csdn net pptde article details 110791950 spm 1001 2101 3001 6661 1 utm medium distribute pc relevant t0 n
  • docker创建CentOS云主机(docker实践)

    基于Ubuntu操作系统 从零开始构建一套docker虚拟化平台 docker的产物为 容器 docker构建容器 Nginx WEB docker启动虚拟机 创建CentOS云主机 同样是容器 对之前内容的总结熟悉 要求 CentOS 7
  • Android实现裁剪

    Android自定义View实现图片缩放旋转移动裁剪 灰信网 软件开发博客聚合 freesion com SuppressLint AppCompatCustomView public class CorpToView extends Im