转载请注明出处:王亟亟的大牛之路
这两天都在写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
记得点个赞哦