一个功能强大的画图板(一)

    **首先在这里声明下,此博客用到了一些博主的博客内容,但是因为电脑系统重装丢了写文件,找不到当时的博客的地址了,如果有知道的还请想告。**
有写博客这个想法很久了,但是因为各种原因没有执行,现在终于下定决心去努力做好这件事了。主要是这不仅可以分享我在学习工作中的心得,而且能够很好的整理我自己的知识思路可谓是双赢的局面。那么闲话好说开始我的第一篇技术博客吧!
既然是图片编辑那么就要有图片我们的图片可以是直接拍照,也可以从相册里选,相关代码比较简单,如下:
/**
     * 在这里我设置了requestWindowFeature(Window.FEATURE_NO_TITLE)属性,但是发现失效,后来研究发现是因为
     * 我们以前继承的是Activity ,而现在继承的是AppCompatActivity,所以此代码失效。生效代码如下
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        if (getSupportActionBar()!=null){
            getSupportActionBar().hide();
        }
        }

 @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.take_photo:
                if (isSdcardExisting()){
                    Intent intent=new Intent("android.media.action.IMAGE_CAPTURE");
                    intent.putExtra(MediaStore.EXTRA_OUTPUT,getImageUri());
                    intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY,0);
                    startActivityForResult(intent,CAMERA_REQUEST_CODE);
                }else {
                    Toast.makeText(v.getContext(), "请插入sd卡", Toast.LENGTH_LONG)
                            .show();
                }
                break;
            case R.id.photos:
                Intent intent =new Intent(Intent.ACTION_GET_CONTENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                intent.setType("image/*");
                startActivityForResult(intent,IMAGE_REQUEST_CODE);
                break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode!=RESULT_OK){
            return;
        }else{
            if (requestCode==IMAGE_REQUEST_CODE){
                EditImage(data.getData());
            }else if (requestCode==CAMERA_REQUEST_CODE){

                if (isSdcardExisting()){
                    EditImage(getImageUri());
                }else {
                    Toast.makeText(this, "请插入sd卡", Toast.LENGTH_LONG)
                            .show();
                }
            }else if (requestCode==RESIZE_REQUEST_CODE){
                if (data!=null){
                    showImage(data);
                }
            }
        }
        super.onActivityResult(requestCode, resultCode, data);

    }
 /**
     * 跳转至照片编辑页面
     * @param uri
     */
    public void EditImage(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.putExtra("crop", "true");
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        intent.putExtra("outputX", 150);
        intent.putExtra("outputY", 150);
        intent.putExtra("return-data", true);
        startActivityForResult(intent, RESIZE_REQUEST_CODE);
    }

这里只贴出来需要跳转的三个系统类,至于如何判断是否存在sd卡以及跳转至主页面的具体操作大家可以自己写下,比较简单。
好了,下面就是我们关键地方了,我们自定义的view,一开始就是一堆初始化:

    private final String TAG=this.getClass().getSimpleName();
    //背景位图
    private Bitmap bitmap_bg=null;
    //前景位图
    private Bitmap bitmap_fg=null;
    //用于画图的画布
    private Canvas mCanvas;
    //画笔
    private Paint mPaint;
    //橡皮
    private Paint mEraser;
    private Path mPath;
    private Matrix mMatrix;
    //画笔的宽度
    private int paintWidth=6;
    //橡皮的大小
    private int eraserWidth=15;
    //图片的规定宽高
    private int bitmapWidth=488;
    private int bitmapHeight=680;
    //图片的原宽高
    private int oldBitmapWidth;
    private int oldBitmapHeight;
    private float scaleX;
    private float scaleY;
    private boolean isStart = true;
    private float lastX;
    private float lastY;
    private paint paintState=paint.PEN;
    /**
     * 判断笔的状态
     */
    private enum paint{
        PEN,ERASER;
    }

 private void init(){
        setFocusableInTouchMode(true); // 确保能接收到触屏事件
        setFocusable(true);
        mMatrix=new Matrix();
        mPath=new Path();
        initPaint();
        initEraser();
    }

    /**
     * 初始化画笔
     */
    private void initPaint(){
        mPaint=new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.RED);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(paintWidth);

    }
    private void initEraser(){
        mEraser=new Paint();
        mEraser.setAntiAlias(true);
        mEraser.setDither(true);
        mEraser.setStyle(Paint.Style.STROKE);
        mEraser.setStrokeJoin(Paint.Join.ROUND);
        mEraser.setStrokeCap(Paint.Cap.ROUND);
        mEraser.setStrokeWidth(eraserWidth);
        mEraser.setColor(Color.TRANSPARENT);
        mEraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    }

通过代码我们可以看出我们是分了前景和后景图的,这样我们在后期的时候操作起来就比较方便了,可以单独的处理前景图和后景图,发现这不是和我们的面向对象语言的封装的特性不谋而合,哈哈。这里面还有一个关键对我们以后的功能拓展起到关键的作用,就是我们将mCanvas中的所有内容通过构造方法保存到了前景图中,这样我们后续的只需要将前景图呈现到初始画布上就可以了,而前景图的放大缩小,平移等操作将只在mCanvas画布上进行,最重要的是我们的画笔不在需要在进行边界的检测了,因为他只会画到我们的前景图上,是不是发现很爽,实现起来非常简单了。
好了图片有了,也初始化了,那么我们就将进行绘画了,说道绘画那肯定少不了我们的触摸事件:

 @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getActionMasked()){
            case MotionEvent.ACTION_DOWN:
                onTouchDown(event);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                onTouchMove(event);
                if (paintState==paint.PEN){
                    mCanvas.drawPath(mPath,mPaint);
                }else if (paintState==paint.ERASER){
                    mCanvas.drawPath(mPath,mEraser);
                }
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                onTouchUp(event);
                invalidate();
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
            default:
                break;
        }
        return true;
    }

    private void  onTouchDown(MotionEvent event){
        isStart=true;
        onTouchMove(event);
    }
    private void  onTouchMove(MotionEvent event){
        float x;
        float y;        
        x=event.getX();
        y=event.getY();
        drawPoint(x,y);
    }
    private void  onTouchUp(MotionEvent event){
        onTouchMove(event);
        isStart=true;
    }

    private void drawPoint(float x, float y){
        //判断是否是起始点
        if (isStart){
            setStartPoint(x,y);
        }else {
            float dx=Math.abs(x-lastX);
            float dy=Math.abs(y-lastY);
            if (dx>=3 || dy>=3){
                mPath.quadTo(lastX, lastY, x, y);
            }

            Log.e(TAG,"move....");
            lastX = x;
            lastY = y;
        }
    }

    private void setStartPoint(float x, float y){
        lastX=x;
        lastY=y;
        mPath.reset();
        mPath.moveTo(x,y);
        isStart=false;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (bitmap_bg!=null){
            canvas.drawBitmap(bitmap_bg,mMatrix,mPaint);
        }
        if (bitmap_fg!=null){
            canvas.drawBitmap(bitmap_fg,0,0,mPaint);

        }
    }

好了,一气呵成,基本实现了绘画的功能了,大家会发现我们的绘画操作基本是在前景图上进行的,我们拓展起功能来就方便多了,接下来我们就要给他添加更加强大的功能了,缩放和平移功能,而且我们的画图板可是在缩放平移后还可以继续正常绘画呢,希望大家继续关注我的下一篇博客。
源码下载链接:画图板(一)

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值