自定义View时,用到Paint Canvas的一些温故,只有想不到没有做不到(实例 1,画一个简单的Activity并且实现他能实现的)
2015-12-30 16:36
876 查看
转载请注明出处:王亟亟的大牛之路
这两天都在写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
记得点个赞哦
相关文章推荐
- 自定义View时,用到Paint Canvas的一些温故,只有想不到没有做不到(实例 1,画一个简单的Activity并且实现他能实现的)
- Inotify测试(2):inotifywait 与 PyInotify 监控层级比较
- HA(high available)集群配置
- jraiser
- shrio 权限管理filterChainDefinitions过滤器配置
- IBM System 服务器做RAID步骤
- nonatomic, retain,weak,strong用法详解
- Raid3.0数据丢失怎么办
- AIDMA VS AISAS vs ISMAS 营销法则
- UltraISO错误提示问题的解决--缺乏权限
- assign,copy,retain之间的区别
- Container View Controller
- Ubuntu 中sendmail 的安装、配置与发送邮件的具体实现
- 责任链模式 Chain of Responsibility
- cocoapods错误You cannot run CocoaPods as root. (CLAide::Help)解决办法
- 浅析 int main(int argc, char *argv[])
- smtp admin email 似乎可以考虑在
- Troubleshooting ‘RPC server unavailable’ 0x800706BA
- LR检查点的if (status == LR_FAIL)写法
- Failed to execute WebDAV PROPPATCH