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. 公有云厂商DDoS防护产品竞品分析——内含CC的一些简单分析,貌似多是基于规则,CC策略细粒度ip/url//ua/refer

    公有云厂商DDoS防护产品竞品分析 from:http://www.freebuf.com/articles/network/132239.html 行文初衷 由于工作关系,最近接触了很多云上用户,对 ...

  2. 大马猴队-Alpha阶段项目复审

    队名 优点 缺点 名次 菜鸡互坑队 经典游戏,情怀加分. 刷新的苹果会在蛇身上出现  14 菜鸡互啄 利用python语言实现git版本管理,典型用户清晰. 没有很好地分析用户痛点,没有测试计划  4 ...

  3. 发现的好东西——bitset

    先向各位大佬介绍一个水题 任何一个正整数都可以用2的幂次方表示.例如 137=2^7+2^3+2^0 同时约定方次用括号来表示,即a^b 可表示为a(b). 由此可知,137可表示为: 2(7)+2( ...

  4. Agilent RF fundamentals (9)-Mixer basics

    Function: change the frequency of the incident RF key parameters ----------------------------------- ...

  5. 字段值为NULL时的like注意事项

    null like '%%'是有问题的 mysql中应该这样写COALESCE($ZU.mobile,'') like '%%' 或者 where IsNull([table].[column],'' ...

  6. About GCC

    GCC used to stand for the GNU C Compiler, but since the compiler supports several other languages as ...

  7. MySQL 5.7.18 在centos下安装记录

    一个朋友找我如何在linux下安装mysql5.7.18,我稍微整理下了下记录,如下: 下载地址: MySQL5.7.18参数官方网址:https://dev.mysql.com/doc/refman ...

  8. requestAnimationFrame 与 cancelAnimationFrame

    API接口 Window对象定义了以下两个接口: partial interface Window { long requestAnimationFrame(FrameRequestCallback ...

  9. asp.net 禁止回车输入

    //只在输入框禁止输入回车 if(event.keyCode==13&&event.srcElement.type=="textarea")    {        ...

  10. 深入理解java虚拟机-第六章

    第6章 类文件 6.3 Class类文件的结构 Class文件是一组以8位字节为基础单位的二进制流. Class文件格式采用一种类似C语言结构伪结构存储数据,这种伪结构中只有两种数据类型:无符号数和表 ...