初学_Android4高级编程-3 自定义View

※创建自定义控件
1.修改现有视图,继承android自带控件,扩展自带控件来定制其外观和行为。
2.直接继承View,SurfaceView类,在一个空画布上创建新的控件

由于效率问题,在自定义的构造函数中完成画刷的创建。
public MyTextVIew(Context context) {
super(context);
Resources resources = getResources();
marginPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
marginPaint.setColor(resources.getColor(R.color.notepad_margin));
linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
linePaint.setColor(resources.getColor(R.color.notepad_lines));
paperColor = resources.getColor(R.color.notepad_pager);
margin = resources.getDimension(R.dimen.notepad_margin);
}

重写onDraw方法修改视图的外观。
@Override
protected void onDraw(Canvas canvas) {
//绘制视图背景色
canvas.drawColor(paperColor);
//绘制边缘
canvas.drawLine(0,0,0,getMeasuredHeight(),linePaint);
canvas.drawLine(0,getMeasuredHeight(),getMeasuredWidth(),getMeasuredHeight(),linePaint);
//绘制marginLeft = margin的竖直线。
canvas.drawLine(margin,0,margin,getMeasuredHeight(),marginPaint);
//Saves the current matrix and clip onto a private stack.
//canvas.save();
//Preconcat the current matrix with the specified translation
canvas.translate(margin,0);
super.onDraw(canvas);
//canvas.restore();
}

当控件的父容器布局它的子控件时,调用onMeasure方法,除非要求恰好占据100*100像素,否则将需要重写。
protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){
//返回高度,宽度
int measuredHeight = measureHeight(heightMeasureSpec);
int measuredWidth = measureWidth(heightMeasureSpec);
setMeasuredDimension(measuredHeight,measuredWidth);
}

在创建复合布局(extends LinearLayout)的时候,在构造函数中使用LayoutInflate填充布局
资源。

视图的输入事件处理
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
return super.onKeyUp(keyCode, event);
}
@Override
public boolean onTrackballEvent(MotionEvent event) {
return super.onTrackballEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}

自定义罗盘的初始化
private void init() {
setFocusable(true);
Resources r = this.getResources();
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(r.getColor(R.color.background_color));
circlePaint.setStrokeWidth(1);
circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);

textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(r.getColor(R.color.text_color));
textPaint.setTextSize(40);

textHeight = (int) textPaint.measureText("yY");

marketPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
marketPaint.setColor(r.getColor(R.color.marker_color));
}
自定义罗盘的视图绘制
@Override
protected void onDraw(Canvas canvas) {
int mMeasureWidth = getMeasuredWidth();
int mMeasureHeight = getMeasuredHeight();
int px = mMeasureWidth / 2;
int py = mMeasureHeight / 2;
int r = Math.min(px, py);

canvas.drawCircle(px, py, r, circlePaint);
canvas.save();
canvas.rotate(-bearing, px, py);

int textWidth = (int) textPaint.measureText("W");
int cardinalX = px - textWidth / 2;
int cardinalY = py - r + textHeight;

for (int i = 0; i < 24; i++) {
canvas.drawLine(px, py - r, px, py - r + 25, marketPaint);
canvas.save();
canvas.translate(0, textHeight);
if (i % 6 == 0) {
String dirString = "";
switch (i) {
case (0):
dirString = "N";
int arrowY = 2 * textHeight;
canvas.drawLine(px, arrowY, px - 5, 3 * textHeight, marketPaint);
canvas.drawLine(px, arrowY, px + 5, 3 * textHeight, marketPaint);
break;
case 6:
dirString = "E";
break;
case 12:
dirString = "S";
break;
case 18:
dirString = "W";
break;
}
canvas.drawText(dirString, cardinalX, cardinalY, textPaint);
} else if (i % 3 == 0) {
String angle = String.valueOf(i * 15);
float angleTextWidth = textPaint.measureText(angle);
int angleTextX = (int) (px - angleTextWidth / 2);
int angleTextY = py - r + textHeight;
canvas.drawText(angle, angleTextX, angleTextY, textPaint);
}
canvas.restore();
canvas.rotate(15, px, py);
}
canvas.restore();
}
自定义罗盘的直径测量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = measure(widthMeasureSpec);
int measuredHeight = measure(heightMeasureSpec);
int d = Math.min(measuredHeight, measuredWidth);
setMeasuredDimension(d, d);
}
private int measure(int measureSpec) {
int result;

//对测量说明进行解码
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);

//没有指定界限
if (specMode == MeasureSpec.UNSPECIFIED) {
result = 200;
} else {
result = specSize;
}
return result;
}

初始指向
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
super.dispatchPopulateAccessibilityEvent(event);
if (isShown()) {
String bearingStr = String.valueOf(bearing);
if (bearingStr.length() > AccessibilityEvent.MAX_TEXT_LENGTH) {
bearingStr = bearingStr.substring(0, AccessibilityEvent.MAX_TEXT_LENGTH);
}
event.getText().add(bearingStr);
return true;
} else {
return false;
}
}

时间: 2024-08-11 12:40:22

初学_Android4高级编程-3 自定义View的相关文章

初学_Android4高级编程-2 Fragment

Fragment允许将activity拆分成多个完全独立封装的可重用控件.每个组件有它自己的生命周期和UI布局.(类似于一个嵌入在activity中的activity)通过继承Fragment来创建一个新的Fragment,大多数情况下,需要为Fragment分配一个UI(xml布局文件),也可以创建一个没有任何UI的后台行为的Fragment. public class MyFragment extends Fragment{ //调用该方法连接它的父Activity @Override pu

初学_Android4高级编程-1 Application单例,及优化布局

※Application每次应用程序运行时,Application类保持实例化状态,Application实现为一个单态(单例),扩展如:import *;public class MyApplication extends Application{ private static MyApplication singleton; public static MyApplication getIntance(){ return singleton; } //创建应用程序是调用,实例化应用程序单态,

初学_Android4高级编程-4 简单的Adapter

※Adapter ·ArrayAdapter 使用泛型把Adapter视图绑定到一个指定类的对象的数组.使用一个对象数组的每个元素的toString值来填充指定布局中的TextView.ArrayList<String> item = new ArrayList<>();ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this,R.layout.item_list,item); ·SimpleAd

读javascript高级编程11-事件

一.事件流 事件流指从页面中接收事件的顺序. 1.事件冒泡(常用) IE中采用的事件流是事件冒泡,先从具体的接收元素,然后逐步向上传播到不具体的元素. 2.事件捕获(少用) Netscapte采用事件捕获,先由不具体的元素接收事件,最具体的节点最后才接收到事件. 3.DOM事件流 DOM2级事件包括三个阶段:事件捕获阶段.处于目标阶段和事件冒泡阶段. 二.事件处理程序 事件处理程序就是响应某些事件的函数,如onclick等. 1. DOM0级事件处理程序 每个元素都有自己的事件处理程序属性,如o

iOS网络高级编程:iPhone和iPad的企业应用开发之错误处理

本章内容 ●    iOS应用中的网络错误源 ●    检测网络的可达性 ●    错误处理的经验法则 ●    处理网络错误的设计模式 到目前为止,我们所介绍的iPhone与其他系统的网络交互都是基于一切正常这个假设.本章将会放弃这个假设,并深入探究网络的真实世界.在真实世界中,事情是会出错的,有时可能是非常严重的错误:手机进入与离开网络.包丢掉或是延迟:网络基础设施出错:偶尔用户还会出错.如果一切正常,那么编写iOS应用就会简单不少,不过遗憾的是现实并非如此.本章将会探讨导致网络操作失败的几

oracle sql 高级编程 历史笔记整理

20130909 周一 oracle sql 开发指南 第7章 高级查询 1.层次化查询select level,ttt.*,sys_connect_by_path(ttt.col1,',') from ttt start with .. Connect by prior -因为先建立树,再进行where过滤的.在where中过滤和在cooonect by中过滤是不一样的. 2.rollup cube高级查询 select grouping(col1) .. From ttt group by

AppWidget实现自定义view的另类实现

一.鸡汤 appwidget是android中小组件,我们经常说的widget其实是指的那些button.textview.imageview等这些小控件,而appwidget则是嵌入到别的app中的activity中显示的一种视图.通常我们的appwidget都是嵌入到luncher应用中的(我们经常说的桌面其实也是一款app也就是home luncher应用,手机里的应用会在其activity内显示一个启动图标),运行在luncher应用中,而其事件处理都是在本app内的进程中完成的,所以这

自定义View系列教程04--Draw源码分析及其实践

通过之前的详细分析,我们知道:在measure中测量了View的大小,在layout阶段确定了View的位置. 完成这两步之后就进入到了我们相对熟悉的draw阶段,在该阶段真正地开始对视图进行绘制. 按照之前的惯例,我们来瞅瞅View中draw( )的源码 public void draw(Canvas canvas) { final int privateFlags = mPrivateFlags; final boolean dirtyOpaque = (privateFlags & PFL

C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(上)

译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(上)),不对的地方欢迎指出与交流. 章节出自<Professional C# 6 and .NET Core 1.0>.水平有限,各位阅读时仔细分辨,唯望莫误人子弟. 附英文版原文:Professional C# 6 and .NET Core 1.0 - Chapter 41 ASP.NET MVC ------------------------------------ 本