自定义View时,用到Paint Canvas的一些温故,只有想不到没有做不到(实例 1,画一个简单的Activity并且实现他能实现的)

转载请注明出处:王亟亟的大牛之路

这两天都在写Paint Canvas 昨天前天都写的比较基础的一些只是和一些简单的Demo演示,那今天就写一个“大气磅礴的”(之前几篇没看的可以看下传送门:http://blog.csdn.net/ddwhan0123/article/details/50426935

废话不多,先上效果

YE? 为什么贴2个一模一样的试图,你错了!不带toCopy按钮的那整个Activity都是画的,并且还有点击事件哦!

再贴一下2张图片(上面张为原图,下面一张为效果图,因为为了让大家看清楚效果,这次的效果图都是50%尺寸的,以前都是20%如果占屏了 抱歉)

是不是不仔细看根本看不出2张图片的差距?

贴一下这个自定义View的布局

<?xml version="1.0" encoding="utf-8"?>
<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="paintcanvasdemo.pro.wjj.paintcanvasdemo.CopyActivity">

    <paintcanvasdemo.pro.wjj.paintcanvasdemo.CustomView.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/customView"/>

</RelativeLayout>

确实就只有他,而且是wrap_content,也就说明我们是整张涂抹,OK先说第一部分


画画

整个页面我把它分位4部分。

1,“ActionBar”部分

2,“不要怂,就是干”文字

3,中间的“妹子”

4,下面的按钮

为了让演示和代码可读性更简易,我声明了4个画笔Paint barPaint, textPaint, bgPaint, buttonPaint;

分别代表 ActionBar的画笔,文字的画笔,背景画笔,按钮画笔

思路:整个图片其实只有2层,背景+控件。

那么先画背景,后画控件,也就不用操作那些试图覆盖的问题了。

实际实现:

  //画背景
  bgPaint = new Paint();
  bgPaint.setColor(getResources().getColor(R.color.White));
  canvas.drawRect(0, 0, ScreenWidth, ScreenHeight, bgPaint);

再是画ActionBar,画之前我们要获取几个参数,1屏幕的长宽,2妹子的长宽,3按钮的长宽。

那么这些参数哪来?

只能从我们的样板,MainActivity来获取控件在正常ImageView,Button的大小:

public class MainActivity extends Activity {
    ImageView imageView;
    Button button3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button toCopy = (Button) findViewById(R.id.toCopy);
        toCopy.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (v.getId() == R.id.toCopy) {
                    Intent intent = new Intent(MainActivity.this, CopyActivity.class);
                    startActivity(intent);
                }
            }
        });
        TypedValue tv = new TypedValue();
        if (this.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
            int actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, this.getResources().getDisplayMetrics());
            Log.d("---> actionBarHeight ", actionBarHeight + "");
        }

        imageView=(ImageView)findViewById(R.id.imageView);
        button3=(Button)findViewById(R.id.button3);
    }

    @Override
    protected void onResume() {
        super.onResume();

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        Log.d("-->image的长,宽", "长 " + imageView.getHeight() + "宽 " + imageView.getWidth());
        Log.d("-->button3的长,宽", "长 " + button3.getHeight() + "宽 " + button3.getWidth());
    }
}

OK,那么我们就可以继续我们的创作

先画Bar的背景蓝色区域,144是测量得来的(其实是谷歌设定的一个值,我没有在别的手机上测试过,不知道这个参数会不会有不同适配,反正我们也就是画着玩,不管那些)

  barPaint = new Paint();
  barPaint.setColor(getResources().getColor(R.color.DoderBlue));
  canvas.drawRect(0, 0, ScreenWidth, 144, barPaint);

再画字

 //画Title
        barPaint.setTextSize(60);
        barPaint.setColor(getResources().getColor(R.color.White));
//        canvas.drawText("PaintCanvasDemo",0,60,barPaint);将不会出现任何东西drawText第一个参数是你要显示的字符,第二个为 x起点,第三个为底部的Y坐标而不是Y的起点,第四个参数就是你的画笔
        Paint.FontMetricsInt fontMetrics = barPaint.getFontMetricsInt();
        int baseline = (144 - fontMetrics.bottom - fontMetrics.top) / 2;
        canvas.drawText("PaintCanvasDemo", 40, baseline, barPaint);

白色的比,垂直居中操作

需要注意的地方标注已写清楚了。

然后再是话我们的文字

         //画 不要怂,就是干
        textPaint = new Paint();
        textPaint.setColor(getResources().getColor(R.color.Black));
        textPaint.setTextSize(80);
        canvas.drawText("不要怂,就是干", 0, 144 + 80, textPaint);

高度就是再我们刚才的Bar下面再加上字高,因为我们的”模版“里没有X向的间距,所以我们也不空了

再接下来就是画妹子了,因为我们妹子图本身是200*200(我记的是),所以我们把她整体的放大了1.5倍,然后再剧中显示,在上一个Activity我们测试出来了,妹子的长宽都是 900,绘画从左上角开始所以都-(2分之一)的边长

        // 定义矩阵对象
        Matrix matrix = new Matrix();
        // 缩放原图
        matrix.postScale(1.5f, 1.5f);
        Bitmap meizi = BitmapFactory.decodeResource(getResources(),
                R.drawable.bg2).copy(Bitmap.Config.ARGB_8888, true);
        Bitmap newMeiZi = Bitmap.createBitmap(meizi, 0, 0, meizi.getWidth(), meizi.getHeight(),
                matrix, true);
        //画妹子
        canvas.drawBitmap(newMeiZi, ScreenWidth / 2 - 450, ScreenHeight / 2 - 450, new Paint());

再之后就是画我们的3个按钮(我只给一个加了点击时间,其实就是坐标的按钮计算很简单,大家一看就明白)

先画灰色的3个背景色块,这边在Y轴方向为了空一些与屏幕底部的间隙我把整个Canvas上移了一些位置,让呈现更符合要求(美感,美感)

每一个按钮都和前一个相距15+自身宽的差距,保持统一性

        buttonPaint = new Paint();
        buttonPaint.setColor(getResources().getColor(R.color.LightGrey));
        canvas.translate(0, -70);
        canvas.drawRect(15, ScreenHeight - 144, 231, ScreenHeight, buttonPaint);
        canvas.drawRect(15 + 231, ScreenHeight - 144, 231 * 2, ScreenHeight, buttonPaint);
        canvas.drawRect(15 + 231 + 231, ScreenHeight - 144, 231 * 3, ScreenHeight, buttonPaint);
        Log.d("--->drawRect1", "15  " + (ScreenHeight - 144) + "  231  " + ScreenHeight);

再是画字,这边的30 的位置差是大致算下来的可能产生误差买单时肉眼不会太明显,强迫症的画。。那您自己算吧

        //居中画字
        buttonPaint.setColor(getResources().getColor(R.color.Black));
        buttonPaint.setTextSize(65);
        canvas.drawText("按钮1", 15 + 30, ScreenHeight - 144 + baseline, buttonPaint);
        canvas.drawText("按钮2", 15 + 30+231, ScreenHeight - 144 + baseline, buttonPaint);
        canvas.drawText("按钮3", 15 + 30+(231*2), ScreenHeight - 144 + baseline, buttonPaint);

点击事件

分析:因为我们的的View一是一个整体,所以不可能把单独的一个”控件“做事件处理,那只能把每一个控件所处的位置的”矩阵“制造成热区的概念,像Html的map标签 (我记的是哦,不对请纠正)

那具体看代码,我再做解释

public class CustomView extends View implements View.OnTouchListener{

    public static interface OnViewOnTouchListener {
        void onTouchClick(View view,MotionEvent event);
    }
    private OnViewOnTouchListener mOnTouchClickListener = null;

    public void setOnTouchClickListener(OnViewOnTouchListener listener) {
        this.mOnTouchClickListener = listener;
    }

    Context context;
    int ScreenWidth, ScreenHeight;
    Paint barPaint, textPaint, bgPaint, buttonPaint;

    public CustomView(Context context) {
        super(context);
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
        setOnTouchListener(this);
    }

    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
        setOnTouchListener(this);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CustomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
        setOnTouchListener(this);
    }

    private void init(Context context, AttributeSet attrs) {
        ScreenWidth = tools.getScreenWidth(context);
        ScreenHeight = tools.getScreenHeight(context);
        Log.d("--->Bar高,宽,长", "Bar高度等于 " + 144 + "ScreenWidth等于 " + ScreenWidth + "ScreenHeight等于 " + ScreenHeight);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画背景色
        bgPaint = new Paint();
        bgPaint.setColor(getResources().getColor(R.color.White));
        canvas.drawRect(0, 0, ScreenWidth, ScreenHeight, bgPaint);

        barPaint = new Paint();
        barPaint.setColor(getResources().getColor(R.color.DoderBlue));
        canvas.drawRect(0, 0, ScreenWidth, 144, barPaint);
        //画Title
        barPaint.setTextSize(60);
        barPaint.setColor(getResources().getColor(R.color.White));
//        canvas.drawText("PaintCanvasDemo",0,60,barPaint);将不会出现任何东西drawText第一个参数是你要显示的字符,第二个为 x起点,第三个为底部的Y坐标而不是Y的起点,第四个参数就是你的画笔
        Paint.FontMetricsInt fontMetrics = barPaint.getFontMetricsInt();
        int baseline = (144 - fontMetrics.bottom - fontMetrics.top) / 2;
        canvas.drawText("PaintCanvasDemo", 40, baseline, barPaint);
        //画 不要怂,就是干
        textPaint = new Paint();
        textPaint.setColor(getResources().getColor(R.color.Black));
        textPaint.setTextSize(80);
        canvas.drawText("不要怂,就是干", 0, 144 + 80, textPaint);
        //画妹子
        // 定义矩阵对象
        Matrix matrix = new Matrix();
        // 缩放原图
        matrix.postScale(1.5f, 1.5f);
        Bitmap meizi = BitmapFactory.decodeResource(getResources(),
                R.drawable.bg2).copy(Bitmap.Config.ARGB_8888, true);
        Bitmap newMeiZi = Bitmap.createBitmap(meizi, 0, 0, meizi.getWidth(), meizi.getHeight(),
                matrix, true);
        //画妹子
        canvas.drawBitmap(newMeiZi, ScreenWidth / 2 - 450, ScreenHeight / 2 - 450, new Paint());

        buttonPaint = new Paint();
        buttonPaint.setColor(getResources().getColor(R.color.LightGrey));
        canvas.translate(0, -70);
        canvas.drawRect(15, ScreenHeight - 144, 231, ScreenHeight, buttonPaint);
        canvas.drawRect(15 + 231, ScreenHeight - 144, 231 * 2, ScreenHeight, buttonPaint);
        canvas.drawRect(15 + 231 + 231, ScreenHeight - 144, 231 * 3, ScreenHeight, buttonPaint);
        Log.d("--->drawRect1", "10  " + (ScreenHeight - 144) + "  231  " + ScreenHeight);
        //居中画字
        buttonPaint.setColor(getResources().getColor(R.color.Black));
        buttonPaint.setTextSize(65);
        canvas.drawText("按钮1", 15 + 30, ScreenHeight - 144 + baseline, buttonPaint);
        canvas.drawText("按钮2", 15 + 30+231, ScreenHeight - 144 + baseline, buttonPaint);
        canvas.drawText("按钮3", 15 + 30+(231*2), ScreenHeight - 144 + baseline, buttonPaint);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (mOnTouchClickListener != null) {
            //注意这里使用getTag方法获取数据
            mOnTouchClickListener.onTouchClick(v,event);
        }
        return true;
    }
}

我们做了个接口。然后这个接口吃了View.OnTouchListener的事件触发,然后我们的调用类去Set一下,那么这个回路就通了。

业务逻辑都在调用类那里做,当然你要写死的画就写到自定义View那去吧。

实现就是如此,是不是很简单啊?

之后考虑做一些动画效果,容我再思索下

源码地址:https://github.com/ddwhan0123/BlogSample/tree/master/PaintCanvasDemo

记得点个赞哦

时间: 2024-11-17 18:06:02

自定义View时,用到Paint Canvas的一些温故,只有想不到没有做不到(实例 1,画一个简单的Activity并且实现他能实现的)的相关文章

自定义View时,用到Paint Canvas的一些温故,讲讲平时一些效果是怎么画的(基础篇 二,图像遮盖,Canvas静态变化)

转载请注明出处:王亟亟的大牛之路 上一篇把简单的一些概念理一理,还画了个圈,那这一篇讲一下图像遮盖"Xfermode"和Canvas的旋转.平移等效果 Xfermode: AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图). PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素异或操作. PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任

自定义View时,用到Paint Canvas的一些温故,自定义Loading控件(动画五,“六边形”的旋转跳跃)

转载请注明出处:王亟亟的大牛之路 最近的一系列文章都是些的自定义控件的绘制,动画等效果,这一片就直接做一个自定义view,上一篇的地址:http://blog.csdn.net/ddwhan0123/article/details/50477030(没看的小伙伴可以看下) 照惯例,贴下演示效果 包结构: 设计分析 黄色为整个控件的整体,绿色部分为绘画出来的六边形,蓝色为一个标准的TextView 问题,为什么不把控件做在一起? 一开始有考虑过直接paint一整个控件把六边形和文字都画出来,想想还

自定义View时,用到Paint Canvas的一些温故,讲讲用路径绘画实现动画效果(基础篇 三)

转载请注明出处王亟亟的大牛之路 上礼拜上了一篇关于动画的自定义View的文章,然后里面的实现是PathMeasure,然后这一部分貌似以前没有讲过,那么就再补一篇来介绍下这部分的知识(之前一篇的传送门:http://blog.csdn.net/ddwhan0123/article/details/51066859) 直接说有点抽象,我们来看下演示的效果: 动的时候,是这样子 那暂停是这样子 其实这样的实现,一个个坐标增量画然后一直Invalidate也能做,但是写起来太麻烦,PathMeasur

自己定义View时,用到Paint Canvas的一些温故,简单的帧动画(动画一 ,&amp;quot;掏粪男孩Gif&amp;quot;顺便再提提onWindowFocusChanged)

转载请注明出处:王亟亟的大牛之路 之前在绘画的过程中提到了静态的旋转啊,缩放啊,平移等一些效果.那么自己定义的View当然也有动态的效果也就是我们的Animation.经常使用的有三种 View Animation Drawable Animation Property Animation 这一篇讲一下简单的Drawable Animation. Drawable Animation实现好是什么个样子呢? 帧动画,一张一张的图片.一次播形成动画的景象. 效果就是如此,把一帧一帧的图品相机播放,形

自定义View(二),强大的Canvas

本文转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0.今天我们主要要了解的是2D相关的,如果你想看3D的话那么可以跳过这篇文章. 大部分2D使用的api都在android.graphics和android.graphics.drawable包中.他们提供了图形处理相关的: C

转载爱哥自定义View系列--Paint详解

上图是paint中的各种set方法 这些属性大多我们都可以见名知意,很好理解,即便如此,哥还是带大家过一遍逐个剖析其用法,其中会不定穿插各种绘图类比如Canvas.Xfermode.ColorFilter等等的用法. set(Paint src) 顾名思义为当前画笔设置一个画笔,说白了就是把另一个画笔的属性设置Copy给我们的画笔,不累赘了 setARGB(int a, int r, int g, int b) 不扯了,别跟我说不懂 setAlpha(int a) 同上 setAntiAlias

手对手的教你用canvas画一个简单的海报

啦啦啦,首先说下需求,产品想让用户在我们app内,分享一张图片到微信.qq等平台.图片中包含用户的姓名.头像.和带着自己信息的二维码.然后,如何生成这张海报呢~~~首先我们老大告诉我有一个插件叫html2canvas.其作用就是可以将dom节点转化成图片,是个不错的东西.我试验了下.确实可以,但~这个插件有点大啊,为了满足海报的这个需求引入这么大的东西感觉很亏!!!所以,还是自己画一个~首先先上效果图 当当当当~~~最后生成的海报中包括头像和姓名与二维码,当然图上的二维码是百度的二维码~最后生成

自定义View时,用到Paint Canvas的一些温故,PropertyAnimation中的ObjectAnimator(动画三,“大大姐”的旋转跳跃)

转载请注明出处:王亟亟的大牛之路 上一篇讲了一些比较基础的view Animation 这篇会选PropertyAnimation的部分功能来讲一下,因为它的子类还是蛮多的,希望分的篇幅多点,然后可以讲细点 先上一下跑的效果(gif吃动画,见谅,大家可以自己run下) 这篇主要会讲以下几部分 - ObjectAnimator - AnimatorSet - PropertyValuesHolder 以及与之相关的一些知识点 Property Animation相对于我们昨天的View Anima

【Android应用开发技术:用户界面】自定义View类设计

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells 设计良好的类总是相似的,它使用一个易用的接口来封装一个特定的功能,它能有效的使用CPU和内存,我们在设计View类时,通常会考虑以下因素: 遵循Android标准规则 提供自定义的风格属性值并能够被Android XML Layout所识别. 发出可访问的事件 能够兼容And