Android 4学习(9):用户界面 - THE ANDROID WIDGET TOOLBOX
Android内置了很多View,包括:
- TextView
- EditText
- Chronometer
- ListView
- Spinner
- Button
- ToggleButton
- ImageButton
- CheckBox
- RedioButton
- ViewFlipper
- VideoView
- QuickContactBadge
- ViewPager
关于View更多的信息,可以参考:http://developer.android.com/guide/tutorials/views/index.html
创建自定义View的三种方式
总的来说,有三种方法来创建新的View:
- 修改已有的View。
- 使用多个已有的View组成新的复合View
- 从头新建一个View
修改已有的View
创建某种View的子类并重写父类的方法,即可通过修改已有View来创建自定义的View,例如:
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.TextView;
public class MyTextView extends TextView {
public MyTextView (Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public MyTextView (Context context) {
Super(context);
}
public MyTextView (Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
[ ... Perform some special processing ... ]
[ ... based on a particular key press ... ]
// Use the existing functionality implemented by
// the base class to respond to a key press event.
return super.onKeyDown(keyCode, keyEvent);
}
}
创建复合控件View
复合控件由多个View组成,是ViewGroup的子类。通过继承ViewGroup并重写父类的构造函数,在构造过程中inflate某个Layout,是常用的生成复合控件的方法之一,例如:
public class ClearableEditText extends LinearLayout {
EditText editText;
Button clearButton;
public ClearableEditText(Context context) {
super(context);
// Inflate the view from the layout resource.
String infService = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater li;
li = (LayoutInflater)getContext().getSystemService(infService);
li.inflate(R.layout.clearable_edit_text, this, true);
// Get references to the child controls.
editText = (EditText)findViewById(R.id.editText);
clearButton = (Button)findViewById(R.id.clearButton);
// Hook up the functionality
hookupButton();
}
}
配置文件:
<?xml version=”1.0” encoding=”utf-8”?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”>
<EditText
android:id=”@+id/editText”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
/>
<Button
android:id=”@+id/clearButton”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:text=”Clear”
/>
</LinearLayout>
使用Layout文件创建复合控件
使用<include>标签可以方便地复用已有的复合View,例如:
<include layout=”@layout/clearable_edit_text”
android:id=”@+id/add_new_entry_input”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_gravity=”top”/>
创建自定义View
通过继承View或SurfaceView,程序员就可以实现自定义的View。View类有一个Canvas对象,可以在上面绘制自己的UI。SurfaceView类有一个Surface对象,Surface支持后台线程绘制,并可以使用OpenGL进行绘制。对于需要经常重绘并且不需要3D效果的UI,推荐使用轻量级的View来实现。
创建新的View
View中的OnMeasure()方法用于确定View的长和高,OnDraw()方法则用于绘制图形,下面是创建一个自定义View的示例代码:
public class MyView extends View {
// Constructor required for in-code creation
public MyView(Context context) {
super(context);
}
// Constructor required for inflation from resource file
public MyView (Context context, AttributeSet ats, int defaultStyle) {
super(context, ats, defaultStyle );
}
//Constructor required for inflation from resource file
public MyView (Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int wMeasureSpec, int hMeasureSpec) {
int measuredHeight = measureHeight(hMeasureSpec);
int measuredWidth = measureWidth(wMeasureSpec);
// MUST make this call to setMeasuredDimension or you will cause a runtime exception when the control is laid out.
setMeasuredDimension(measuredHeight, measuredWidth);
}
private int measureHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
[ ... Calculate the view height ... ]
return specSize;
}
private int measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
[ ... Calculate the view width ... ]
return specSize;
}
@Override
protected void onDraw(Canvas canvas) {
[ ... Draw your visual interface ... ]
}
}
重写onDraw()方法
@Override
protected void onDraw(Canvas canvas) {
// Get the size of the control based on the last call to onMeasure.
int height = getMeasuredHeight();
int width = getMeasuredWidth();
// Find the center
int px = width/2;
int py = height/2;
// Create the new paint brushes.
// NOTE: For efficiency this should be done in the views’s constructor
Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(Color.WHITE);
// Define the string.
String displayText = “Hello World!”;
// Measure the width of the text string.
float textWidth = mTextPaint.measureText(displayText);
// Draw the text string in the center of the control.
canvas.drawText(displayText, px-textWidth/2, py, mTextPaint);
}
重写OnMeasure()方法
Android中View的默认大小是100*100像素,重写OnMeasure()方法,可以实现自定义长和宽:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredHeight = measureHeight(heightMeasureSpec);
int measuredWidth = measureWidth(widthMeasureSpec);
setMeasuredDimension(measuredHeight, measuredWidth);
}
private int measureHeight(int measureSpec) {
// Return measured widget height.
}
private int measureWidth(int measureSpec) {
// Return measured widget width.
}
处于效率的考虑,measureSpec和measureSpec直接作为int参数传给了onMeasure(),但在使用之前,首先要decode:
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
下面的代码是一个典型的处理Measure的例子:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredHeight = measureHeight(heightMeasureSpec);
int measuredWidth = measureWidth(widthMeasureSpec);
setMeasuredDimension(measuredHeight, measuredWidth);
}
private int measureHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
// Default size if no limits are specified.
int result = 500;
if (specMode == MeasureSpec.AT_MOST) {
// Calculate the ideal size of your control within this maximum size.
// If your control fills the available space return the outer bound.
result = specSize;
} else if (specMode == MeasureSpec.EXACTLY) {
// If your control can fit within these bounds return that value.
result = specSize;
}
return result;
}
private int measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
// Default size if no limits are specified.
int result = 500;
if (specMode == MeasureSpec.AT_MOST) {
// Calculate the ideal size of your control within this maximum size.
// If your control fills the available space return the outer bound.
result = specSize;
} else if (specMode == MeasureSpec.EXACTLY) {
// If your control can fit within these bounds return that value.
result = specSize;
}
return result;
}
处理UI交互事件
通过重写类似下面列举的这些方法,可以处理常见的UI交互事件:
- onKeyDown
- onKeyUp
- onTrackballEvent
- onTouchEvent
Android 4学习(9):用户界面 - THE ANDROID WIDGET TOOLBOX的更多相关文章
- Android Sip学习(三)Android Voip实现
Android Sip学习(三)Android Voip实现 Android Sip学习(准备知识)SIP 协议完整的呼叫流程 Android Sip学习(一)Android 2.3 APIs S ...
- Android FrameWork学习(二)Android系统源码调试
通过上一篇 Android FrameWork学习(一)Android 7.0系统源码下载\编译 我们了解了如何进行系统源码的下载和编译工作. 为了更进一步地学习跟研究 Android 系统源码,今天 ...
- android菜鸟学习笔记5----第一个android程序
程序功能:点击一个按钮,然后弹出一个提示信息 Step 1:在eclipse中新建一个android application project,在创建过程中不勾选create activity,这样就创 ...
- Android开发学习总结(二)——使用Android Studio搭建Android集成开发环境
有很长一段时间没有更新博客了,最近实在是太忙了,没有时间去总结,现在终于可以有时间去总结一些Android上面的东西了,很久以前写过这篇关于使用Android Studio搭建Android集成开发环 ...
- android开发学习 ------- 【转】 android中的单例模式 (详解)
https://blog.csdn.net/u011418943/article/details/60139644 这篇文章 前因后果 都说出来了 ,值得学习. https://blog.cs ...
- Android开发学习之三——第一个Android程序
下面我们建立第一个Android程序. 打开Eclipse,开始如下步骤: 1.File ==> New ==> Android Application Project 出现如下窗口: 2 ...
- 吴裕雄--天生自然Android开发学习:下载安装android stuio集成开发工具
下载链接: https://developer.android.google.cn/index.html
- Android 开发学习进程0.17 Android资源文件selector textview显示两种不同字体
selector 是安卓资源文件的一种,它可以使按钮等实现不同状态下的不同UI,不用在代码中实现,而使用方式有两种,一种在color文件下 创建.xml可以使按钮等字体在不同状态下的变化,其二是在dr ...
- android开发学习 ------- 【转】 android事件分发机制 和 自定义view涉及的事件分发
参考 https://blog.csdn.net/carson_ho/article/details/54136311 ,写的很完美,原理入门的一篇博客,看这一篇就够了 https://www. ...
- android开发学习 ------- 【转】 android中的线程池
线程很常见 , https://blog.csdn.net/seu_calvin/article/details/52415337 参考,保证能看懂.
随机推荐
- 20165210 Java第五次实验报告
20165210 实验五 网络编程与安全 网络编程与安全一: 实验要求: 两人一组结对编程: 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA ...
- 2017.10.30 Epicor -ERP
1 公司新用ERP系统,做使用培训,mark... This course reviews the project management flow in the Epicor application. ...
- socket INADDR_ANY
linux下的socket INADDR_ANY表示的是一个服务器上所有的网卡(服务器可能不止一个网卡)多个本地ip地址都进行绑定端口号,进行侦听. 不光是多个网卡的问题. 见如下server lis ...
- 深入分析AIDL原理
深入分析AIDL原理 分类: Android2011-11-18 17:29 6522人阅读 评论(1) 收藏 举报 descriptorcallbackservicenullinterfaceser ...
- Windows下Python安装lxml
1.下载easy_install的安装包,下载地址:https://pypi.Python.org/pypi/setuptools 我是Windows7,所以直接下载Windows(Simplify) ...
- spring的笔记1 关云长
1.1 实例化方式 l 3种bean实例化方式:默认构造.静态工厂.实例工厂 1.1.1 默认构造 <bean id="" class=""> ...
- iOS UI调试工具 -- UIDebuggingInformationOverlay
英文原文: http://ryanipete.com/blog/ios/swift/objective-c/uidebugginginformationoverlay/ 无意中看到iOS自带调试工具 ...
- GIT多人合作开发
. 建立代码仓库(专门用于团队开发的代码仓库) ============================================================================ ...
- 系列文章--SharePoint 2013 开发教程
做了SharePoint有三年了,大家经常会问到,你的SharePoint是怎么学的,想想自己的水平,也不过是初级开发罢了.因为,SharePoint开发需要接触的东西太多了,Windows操作系统. ...
- pidstat
统计系统上的某个进程占用的磁盘读写 pidstat -d -p pidNumber 3 -d 表示磁盘设备 -p 指定pid 3 表示每三秒刷新一次结果