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. day5-hashlib模块

    一.概述 在程序开发过程中,很多时候会涉及用户信息验证环节,这类场景下我们往往需要对字符串进行加密处理.python中也有专门的加密模块,它就是hashlib.下面章节将详述它的常见用法. 二.常见加 ...

  2. 实战 Windows Server 2012 群集共享卷

    群集共享卷,简单理解就是一个针对Hyper-V优化的一个分布式访问文件系统,群集中的节点可以同时写到一个磁盘,并且是受控访问,以避免写数据的冲突.此功能和Vmware  的VMFS是类似的.此功能从W ...

  3. LeetCode OJ:Reverse Linked List (反转链表)

    Reverse a singly linked list. 做II之前应该先来做1的,这个倒是很简单,基本上不用考虑什么,简单的链表反转而已: /** * Definition for singly- ...

  4. 软工作业-wc(Python实现)

    GitHub地址:GitHub PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划  30  40 · Esti ...

  5. Android 中的BroadCastReceiver

    BroadCastReceiver 简介 (末尾有源码) BroadCastReceiver 源码位于: framework/base/core/java/android.content.Broadc ...

  6. JS 页面加载触发事件 document.ready和onload的区别

    document.ready和onload的区别——JavaScript文档加载完成事件页面加载完成有两种事件: 一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件): 二是onlo ...

  7. rebar安装及创建项目

    rebar作为erlang开发中编译,构建,发布,打包,动态升级的常用工具,下面我记录下rebar工具的安装及使用 从源码安装rebar 1. 建立文件 install_rebar.sh 2. 拷贝如 ...

  8. webservice WS-RS独立发布

    一.基本介绍 Web Services是一个软件接口,它描述了一组可以在网络上通过标准化的 XML 消息传递访问的操作.它使用基于 XML 语言的协议来描述要执行的操作或者要与另一个 Web 服务交换 ...

  9. 十二、python沉淀之路--内置函数

    1.abs函数,求绝对值. a = abs(-3) print(a) 返回:3 2.all函数:判断是否是可迭代对象. 官方解释:Return True if bool(x) is True for ...

  10. maven命令行创建web项目报错:java.lang.NoClassDefFoundError: org/apache/commons/lang/StringUtils

    早上一上班就想新建一个web项目玩玩,没想到一敲命令创建就失败了,真是出师不利.各种折腾无果,当然我也可以用eclipse直接创建的,就是不甘心被这破问题给耍了.刚刚才发现问题原因,这个结果我也是醉了 ...