zoukankan      html  css  js  c++  java
  • Android 4学习(9):用户界面

    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

    通过继承ViewSurfaceView,程序员就可以实现自定义的ViewView类有一个Canvas对象,可以在上面绘制自己的UISurfaceView类有一个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()方法

    AndroidView的默认大小是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.
    }

    处于效率的考虑,measureSpecmeasureSpec直接作为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

  • 相关阅读:
    Python Revisited Day 13 (正则表达式)
    Python Revisited Day 06 (面向对象程序设计)
    Python Revisited (变量)
    Python Revisited Day 05(模块)
    Python Revisited Day 04 (控制结构与函数)
    Python Revisited Day 03 (组合数据类型)
    Numpy
    Python Revisited Day 01
    Python3使用openpyxl读写Excel文件
    Python3操作YAML文件
  • 原文地址:https://www.cnblogs.com/jubincn/p/3381640.html
Copyright © 2011-2022 走看看