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的更多相关文章

  1. Android Sip学习(三)Android Voip实现

    Android Sip学习(三)Android Voip实现   Android Sip学习(准备知识)SIP 协议完整的呼叫流程 Android Sip学习(一)Android 2.3 APIs S ...

  2. Android FrameWork学习(二)Android系统源码调试

    通过上一篇 Android FrameWork学习(一)Android 7.0系统源码下载\编译 我们了解了如何进行系统源码的下载和编译工作. 为了更进一步地学习跟研究 Android 系统源码,今天 ...

  3. android菜鸟学习笔记5----第一个android程序

    程序功能:点击一个按钮,然后弹出一个提示信息 Step 1:在eclipse中新建一个android application project,在创建过程中不勾选create activity,这样就创 ...

  4. Android开发学习总结(二)——使用Android Studio搭建Android集成开发环境

    有很长一段时间没有更新博客了,最近实在是太忙了,没有时间去总结,现在终于可以有时间去总结一些Android上面的东西了,很久以前写过这篇关于使用Android Studio搭建Android集成开发环 ...

  5. android开发学习 ------- 【转】 android中的单例模式 (详解)

    https://blog.csdn.net/u011418943/article/details/60139644     这篇文章 前因后果 都说出来了 ,值得学习. https://blog.cs ...

  6. Android开发学习之三——第一个Android程序

    下面我们建立第一个Android程序. 打开Eclipse,开始如下步骤: 1.File ==> New ==> Android Application Project 出现如下窗口: 2 ...

  7. 吴裕雄--天生自然Android开发学习:下载安装android stuio集成开发工具

    下载链接: https://developer.android.google.cn/index.html

  8. Android 开发学习进程0.17 Android资源文件selector textview显示两种不同字体

    selector 是安卓资源文件的一种,它可以使按钮等实现不同状态下的不同UI,不用在代码中实现,而使用方式有两种,一种在color文件下 创建.xml可以使按钮等字体在不同状态下的变化,其二是在dr ...

  9. android开发学习 ------- 【转】 android事件分发机制 和 自定义view涉及的事件分发

    参考  https://blog.csdn.net/carson_ho/article/details/54136311   ,写的很完美,原理入门的一篇博客,看这一篇就够了 https://www. ...

  10. android开发学习 ------- 【转】 android中的线程池

    线程很常见 , https://blog.csdn.net/seu_calvin/article/details/52415337    参考,保证能看懂.

随机推荐

  1. vue项目中报常见错误

    最近做项目,添加了less样式之后报错, 添加了如下样式: 报错如下图: 于是,就把相关的依赖也都安装了 以为这样会好使啦,后来发现原来是vue-style-loader的问题, 安装的vue-sty ...

  2. MongoDB 可视化管理工具 MongoCola-1.1.0 测试版发布

    首先,感谢大家对于本工具的支持. 经过一周的努力,最新版的工具测试版出炉了,这个版本是一个很重要的版本. 为什么说这个版本重要?以前的工具,只支持一个视图窗口,也就是说了,一次只能看一个数据集的数据. ...

  3. 获取Activity的返回参数

    一.新建一个空的工程 二.在主界面中添加一个按钮和一个TextView组件 三.新建一个空的activity,命名为TheAty,并添加一个按钮和一个EditText组件 四.重写TheAty的源代码 ...

  4. Android中UI线程与后台线程交互设计的6种方法

    在android的设计思想中,为了确保用户顺滑的操作体验.一些耗时的任务不能够在UI线程中运行,像访问网络就属于这类任务.因此我们必须要重新开启 一个后台线程运行这些任务.然而,往往这些任务最终又会直 ...

  5. CABAC与CAVLC有什么区别?

    待完善 7.3.12 用 CAVLC 方式编码的残差数据的语义 coeff_token   指明了非零系数的个数,拖尾系数的个数. trailing_ones_sign_flag 拖尾系数的符号 - ...

  6. 使用 DocFX 生成 .Net/Unity项目文档

    孙广东  2017.5.27 http://blog.csdn.NET/u010019717 微软开源全新的文档生成工具DocFX   类似JSDoc或Sphinx     如何使用看 : http: ...

  7. PHP防止mysql注入方法

    本文纲要: 1. 初始化你的变量 2. 一定记得要过滤你的变量 [一.在服务器端配置] 安全,PHP代码编写是一方面,PHP的配置更是非常关键. 我们php手手工安装的,php的默认配置文件在 /us ...

  8. 前端之css样式02

    一.float属性 block元素通常被现实为独立的一块,独占一行,多个block元素会各自新起一行,默认block元素宽度自动填满其父元素宽度.block元素可以设置width.height.mar ...

  9. 【转载】GetAdaptersInfo函数在64位系统上返回ERROR_NOACCESS的有关问题

    From:http://www.educity.cn/wenda/351190.html GetAdaptersInfo函数在64位系统下返回ERROR_NOACCESS的问题 实际应用中一个程序在长 ...

  10. CSS3的圆角border-radius属性

    一,语法解释 border-radius : none | <length>{1,4} [/ <length>{1,4} ] <length>: 由浮点数字和单位标 ...