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

  • 相关阅读:
    [苹果maccms] MACCMS苹果cms宝塔定时任务添加教程说明
    [苹果cmsV10]新版本演员库分类报无权限问题和解决方法!
    CentOS 6.8安装Python2.7.13
    [HOWTO] Install Sphinx for A Script Pro
    A Script Pro nginx URL重写规则无法播放MP4解决方法
    随机跳转
    UI库
    vuex
    vue 数据请求
    vue守卫、储存与路由模式
  • 原文地址:https://www.cnblogs.com/jubincn/p/3381640.html
Copyright © 2011-2022 走看看