【Android学习】View

1,概念

1)View

是Android中所有控件(Button、RelativeLayout、ListView)的基类。

View可以是单个控件也可以是多个控件(ViewGroup)组成的一组控件。

2)ViewGroup(控件组)

①概念

包含一组View,同时也继承了View。

RelativeLayout不但是一个View,也是一个ViewGroup。
Android的UI界面都是由View和ViewGroup及其派生类组合而成的。其中,View是所有UI组件的基类,而ViewGroup是容纳这些组件的容器,其本身也是从View派生出来的,也就是说ViewGroup的父类就是View。

②FrameLayout(框架布局,帧布局)

布局中所有的控件都会默认出现在视图的左上角,

注意:帧布局中,第一个布局放在底层,按层次叠放。(注意覆盖问题)

③LinearLayout(线性布局)

android:orientation=“horizontal|vertical"
android:layout_gravity="right|left|top|bottom"

orientation属性不设置时默认为horizontal。此时第一个控件的宽度若设置成“fill_parent”,后面添加的组件将都无法看到。

④AbsoluteLayout(绝对布局)

可以放置多个控件,并且可以自己定义控件的x,y位置。

⑤RelativeLayout(相对布局)

同样可以达到FrameLayout的效果。
相关属性:

      android:layout_centerInParent="true|false"
      android:layout_centerHorizontal="true|false"
      android:layout_alignParentRight="true|false"

RelativeLayout中的子view靠右失效问题:
使用android:layout_alignParentRight=”true”时,若同时使用android:layout_toRightOf则会使android:layout_alignParentRight失效。

⑥TableLayout(表格布局)

将子元素的位置分配到行或列中,一个TableLayout由许多的TableRow组成。
是LinearLayout子类。

<TableLayout><TableRow></TableRow></TableLayout>

3)实现阴影方式

①Android5.x中的阴影效果elevation和translationZ

Android5.x中 view多了一个 属性 z,垂直高度上的变化。
Z属性 由两部分组成,elevation 和 translationZ; eleavation是静态的成员,translationZ是用来做动画。

Z = elevation + translationZ

    <ImageView 
    android:id="@+id/me_daijjBack" 
    android:layout_width="27dp" 
    android:layout_height="27dp" 
    android:translationZ="5dp" 
    android:src="@drawable/shape_back" />
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {        
    btn.setElevation(3f); 
} 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    btn.setTranslationZ(5f); 
}

注意:
1. view的大小要比它的父布局小,才会有阴影效果,如果相同大小,是看不到阴影效果的;
2. 给图片设置阴影的时候,如果这种图片的background属性是shape,那直接通过xml设置阴影是OK的,但是,如果是一张png或者其他格式的图片,直接通过xml设置android:elevation="2dp" android:translationZ="2dp"阴影是看不到效果的,得通过其他代码设置才行。。。

②CardView

CardView 扩展 FrameLayout 类并让您能够显示卡片内的信息,这些信息在整个平台中拥有一致的呈现方式。CardView 小部件可拥有阴影和圆角。
如果要使用阴影创建卡片,请使用 card_view:cardElevation 属性。CardView 在 Android 5.0(API 级别 21)及更高版本中使用真实高度与动态阴影,而在早期的 Android 版本中则返回编程阴影实现。

③轮廓设置:android:outlineProvider

实现方式:
①通过shape设置的背景,view会自动根据shape的形状进行轮廓判定,
②通过color设置的背景,view默认其轮廓和view的大小一样。
③但是通过图片进行背景设置,view则无法获知轮廓的形状,这个时候就需要手动进行指定了。

注意:
1,none即使设置了Z属性,也不会显示阴影
2,background会按照背景来设置阴影形状
3,bounds会按照view的大小来描绘阴影

对于①和②这种情况,也是可以通过设置android:outlineProvider
来改变阴影的形状以及轮廓外观的。

对于③这种背景是一张png或者其他格式的图片的情况,
android:outlineProvider=“background”是没有效果的,属性设置成android:outlineProvider=bounds虽然也是有效果的,但是阴影轮廓是一个方形的轮廓,并不是我们想要的效果了。

不设置android:outlineProvider属性就更没有效果了。

2,View的位置参数

top、left、right、bottom。
Android3.0增加的参数:x、y(View左上角的坐标)、translationX、translationY(View左上角相对于父容器的偏移量,默认值为0)。

x = left + translationX;
y = top + translationY.

3,事件

当手指触摸到View或ViewGroup派生的控件后,将会触发一系列的触发响应事件,如:
onTouchEvent、onClick、onLongClick等。每个View都有自己处理事件的回调方法,开发人员只需要重写这些回调方法,就可以实现需要的响应事件。

1)MotionEvent

ACTION_DOWN  手指刚接触屏幕;
ACTION_MOVE  手指在屏幕上移动;
ACTION_UP    手机从屏幕上松开的一瞬间。

该事件提供的两组方法:
getX/getY:相对于当前View左上角的x和y坐标。
getRawX/getRawY:相对于手机屏幕左上角的坐标。

TouchSlop是系统所能识别出的被认为最小的滑动距离(小于这个距离判定为不滑动)。

2)VelocityTracker(速度追踪)

用于追踪手指在滑动过程中的速度,包括水平和垂直方向的速度。

3)GestureDetector(手势检测)

用于辅助检测用户的单击、滑动、长按、双击等行为。
实际开发中,可以在View的onTouchEvent方法中实现所需的监听。

//OnGestureLisstener和OnDoubleTapListener方法:
--onSingleTapUp(单击)
--onFling(快速滑动)
--onScroll(拖动)
--onLongPress(长按)
--onDoubleTap(双击)

4)滑动

实现方式有三种:

①使用scrollTo/scrollBy

操作简单,但只能改变View内容的位置,不能改变View本身的位置。

mScrollX
mScrollY 为View上边缘和View内容上边缘在竖直方向的举例。当View上边缘在View内容上边缘的下边时,为正值,否则为负值。

②给View施加平移动画

采用传统的View动画或属性动画都可以实现。
主要是操作View的translationX和translationY属性。

缺点:如果动画元素不需要响应用户的交互可以使用。
优点:可以实现复杂的效果。

③改变View的LayoutParams使得View重新布局

实现麻烦,操作灵活,使用于一些交互性强的View.

5)弹性滑动

渐进式滑动。主要实现有三种:

①Scroller

②动画

③延时策略

a.Handler的postDelayed方法
b.View的postDelayed方法
c.Thread的sleep方法
在while循环中不断地滑动View和sleep

4,事件分发机制

1)事件分发过程

当一个MotionEvent产生后,系统要把这个事件传递给一个具体的View,这个传递的过程就是分发过程。
“分发”是指一个触摸或点击的事件发生,分发给当前触摸控件所监听的事件(如OnClick、onTouch等),进而来决定是控件的哪个函数来响应此次事件。
如果是ViewGroup和View,事件传递的顺序是从底向上传递的。响应正好相反,是自上而下。

①public boolean dispatchTouchEvent(MotionEvent ev)

用来进行事件的分发。
返回值表示当前控件是否消费了传递过来的事件:消费了为true,否则返回false(交由子控件处理)。

②public boolean onInterceptTouchEvent(MotionEvent event)

只有ViewGroup才有,表示是否拦截到子控件(上层控件)的事件。
默认返回false不拦截,传递给子控件(上层View或ViewGroup)处理。
如果返回true,表示拦截,交由自己父类的dispatchTouchEvent处理。

③public boolean onTouchEvent(MotionEvent event)

负责执行事件的处理。
主要处理MotionEvent.ACTION_DOWN、MotionEvent.ACTION_MOVE 、MotionEvent.ACTION_UP这三个事件。

参数event为手机屏幕触摸事件封装类的对象,其中封装了该事件的所有信息,例如触摸的位置、触摸的类型以及触摸的时间等。该对象会在用户触摸手机屏幕时被创建。

View事件的分发过程:
View事件的分发过程
ViewGroup事件的分发过程:
ViewGroup事件的分发过程

2)注意

①一个事件序列只能被一个View拦截且消耗。
②某个View一旦开始处理事件,则不再消耗ACTION_DOWN事件(onTouchEvent返回了false),同一事件序列中的其他事件将交给它的父元素去处理。

3)本质

事件从哪个对象发出,经过哪些对象,最终由哪个对象处理了该事件。此处对象指的是Activity、Window与View。

4)分发顺序

Activity(Window) -> ViewGroup -> View
这里写图片描述
dispatchTouchEvent 和 onTouchEvent 一旦return true,事件就停止传递了(到达终点)(没有谁能再收到这个事件)。

Android事件的分发主要由三个方法来完成,如下所示:

// 父View调用dispatchTouchEvent()开始分发事件
public boolean dispatchTouchEvent(MotionEvent event){
    boolean consume = false;
    // 父View决定是否拦截事件
    if(onInterceptTouchEvent(event)){
        /*父View调用onTouchEvent(event)消费事件,如果该方法返回true,
     *表示该View消费了该事件,后续该事件序列的事件(Down、Move、Up)将不会在传递给其他View。
         */ 
        consume = onTouchEvent(event);
    }else{
        // 调用子View的dispatchTouchEvent(event)方法继续分发事件
        consume = child.dispatchTouchEvent(event);
    }
    return consume;
}

5,View常见回调方法

1)构造方法

2)onAttach

3)onVisibilityChanged

4)onDetach

6,View绘制原理

View的绘制流程主要分为三步:

1)onMeasure

测量视图的大小,从顶层父View到子View递归调用measure()方法,measure()调用onMeasure()方法,onMeasure()方法完成绘制工作。

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
//参数:这两个值是由父视图经过计算后传递给子视图的。 

2)onLayout

确定视图的位置,从顶层父View到子View递归调用layout()方法,父View将上一步measure()方法得到的子View的布局大小和布局参数,将子View放在合适的位置上。

3)onDraw

绘制最终的视图,首先ViewRoot创建一个Canvas对象,然后调用onDraw()方法进行绘制。
onDraw()方法的绘制流程为:① 绘制视图背景。② 绘制画布的图层。 ③ 绘制View内容。④ 绘制子视图,如果有的话。⑤ 还原图层。⑥ 绘制滚动条。

4)requestLayout()、invalidate()与postInvalidate()

一般说来需要重新布局就调用requestLayout()方法,需要重新绘制就调用invalidate()方法。

①requestLayout()

该方法会递归调用父窗口的requestLayout()方法,直到触发ViewRootImpl的performTraversals()方法,此时mLayoutRequestede为true,会触发onMesaure()与onLayout()方法,不一定
会触发onDraw()方法。

②invalidate()

该方法递归调用父View的invalidateChildInParent()方法,直到调用ViewRootImpl的invalidateChildInParent()方法,最终触发ViewRootImpl的performTraversals()方法,此时mLayoutRequestede为false,不会触发onMesaure()与onLayout()方法,当时会触发onDraw()方法。

③postInvalidate()

该方法功能和invalidate()一样,只是它可以在非UI线程中调用。

7,自定义View

1)自定义控件要求

 1. 应当遵守Android标准的规范(命名,可配置,事件处理等)。
 2. 在XML布局中可配置控件的属性。
 3. 对交互应当有合适的反馈,比如按下,点击等。
 4. 具有兼容性, Android版本很多,应该具有广泛的适用性。

2)自定义控件基本原理

View的绘制基本上由measure()、layout()、draw()这个三个函数完成

①自定义属性的声明和获取

分析需要的自定义属性
在res/values/attrs.xml定义声明
在layout文件中进行使用
在View的构造方法中进行获取

②测量onMeasure

测量-Measure过程是计算视图大小,View measure过程相关方法主要有三个:

public final void measure(int widthMeasureSpec, int heightMeasureSpec)  
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight)  
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  

measure调用onMeasure,onMeasure测量宽度、高度然后调用setMeasureDimension保存测量结果;
measure、setMeasureDimension是final类型,view的子类不需要重写,onMeasure在view的子类中重写。

关于MeasureSpec:
(1) UPSPECIFIED :父容器对于子容器没有任何限制,子容器想要多大就多大.
(2) EXACTLY父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间.
(3) AT_MOST子容器可以是声明大小内的任意大小.

③布局onLayout(ViewGroup)

布局-Layout过程用于设置视图在屏幕中显示的位置,View layout过程相关方法主要要三个:

public void layout(int l, int t, int r, int b)
protected boolean setFrame(int left, int top, int right, int bottom)
protected void onLayout(boolean changed, int left, int top, int right, int bottom)

layout通过调用setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,onLayout一般只会在自定义ViewGroup中才会使用

④绘制onDraw

绘制-draw过程主要用于利用前两步得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。

public void draw(Canvas canvas)
protected void onDraw(Canvas canvas)

通过调用draw函数进行视图绘制,在View类中onDraw函数是个空函数,最终的绘制需求需要在自定义的onDraw函数中进行实现,比如ImageView完成图片的绘制,如果自定义ViewGroup这个函数则不需要重载。

⑤onTouchEvent

⑥onInterceptTouchEvent(ViewGroup)

⑦状态的恢复与保存

3)实现

自定义控件的实现有三种方式,分别是:组合控件、自绘控件和继承控件。

①组合控件

将一些小的控件组合起来形成一个新的控件,这些小的控件多是系统自带的控件。比如很多应用中普遍使用的标题栏控件。

title_bar.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#0000ff" >
    <Button
        android:id="@+id/left_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_margin="5dp"
        android:background="@drawable/back1_64" />
    <TextView
        android:id="@+id/title_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="这是标题"
        android:textColor="#ffffff"
        android:textSize="20sp" />
</RelativeLayout>
public class TitleView extends RelativeLayout {
    private Button mLeftBtn;
    private TextView mTitleTv;
    public TitleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 加载布局
        LayoutInflater.from(context).inflate(R.layout.title_bar, this);
        mLeftBtn = (Button) findViewById(R.id.left_btn);
        mTitleTv = (TextView) findViewById(R.id.title_tv);
    }
    // 为左侧返回按钮添加自定义点击事件
    public void setLeftButtonListener(OnClickListener listener) {
        mLeftBtn.setOnClickListener(listener);
    }
    // 设置标题的方法
    public void setTitleText(String title) {
        mTitleTv.setText(title);
    }
}

②自绘控件

自绘控件的内容都是自己绘制出来的,在View的onDraw方法中完成绘制。下面就实现一个简单的计数器,每点击它一次,计数值就加1并显示出来。

public class CounterView extends View implements OnClickListener {

    // 定义画笔
    private Paint mPaint;
    // 用于获取文字的宽和高
    private Rect mBounds;
    // 计数值,每点击一次本控件,其值增加1
    private int mCount;

    public CounterView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 初始化画笔、Rect
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBounds = new Rect();
        // 本控件的点击事件
        setOnClickListener(this);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        mPaint.setColor(Color.BLUE);
        // 绘制一个填充色为蓝色的矩形
        canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);

        mPaint.setColor(Color.YELLOW);
        mPaint.setTextSize(50);
        String text = String.valueOf(mCount);
        // 获取文字的宽和高
        mPaint.getTextBounds(text, 0, text.length(), mBounds);
        float textWidth = mBounds.width();
        float textHeight = mBounds.height();

        // 绘制字符串
        canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2
                + textHeight / 2, mPaint);
    }
    @Override
    public void onClick(View v) {
        mCount ++;
        // 重绘
        invalidate();
    }
}

这里写图片描述

③继承控件

就是继承已有的控件,创建新控件,保留继承的父控件的特性,并且还可以引入新特性.

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;

public class ClearEditText extends EditText implements View.OnFocusChangeListener, TextWatcher {

    private Drawable mClearDrawable;
    private boolean hasFocus;

    public ClearEditText(Context context) {
        this(context, null);
    }

    public ClearEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ClearEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        // getCompoundDrawables() Returns drawables for the left(0), top(1), right(2) and bottom(3)
        mClearDrawable = getCompoundDrawables()[2]; // 获取drawableRight
        if (mClearDrawable == null) {
            // 如果为空,即没有设置drawableRight,则使用R.mipmap.close这张图片
            mClearDrawable = getResources().getDrawable(R.mipmap.close);
        }
        mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
        setOnFocusChangeListener(this);
        addTextChangedListener(this);
        // 默认隐藏图标
        setDrawableVisible(false);
    }

    /**
     * 我们无法直接给EditText设置点击事件,只能通过按下的位置来模拟clear点击事件
     * 当我们按下的位置在图标包括图标到控件右边的间距范围内均算有效
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            if (getCompoundDrawables()[2] != null) {
                int start = getWidth() - getTotalPaddingRight() + getPaddingRight(); // 起始位置
                int end = getWidth(); // 结束位置
                boolean available = (event.getX() > start) && (event.getX() < end);
                if (available) {
                    this.setText("");
                }
            }
        }
        return super.onTouchEvent(event);
    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        this.hasFocus = hasFocus;
        if (hasFocus && getText().length() > 0) {
            setDrawableVisible(true); // 有焦点且有文字时显示图标
        } else {
            setDrawableVisible(false);
        }
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int count, int after) {
        if (hasFocus) {
            setDrawableVisible(s.length() > 0);
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void afterTextChanged(Editable s) {
    }

    protected void setDrawableVisible(boolean visible) {
        Drawable right = visible ? mClearDrawable : null;
        setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
    }
}

4)优化

①降低刷新频率

i> 优化onDraw()方法

减少冗余代码:减少GC
减少调用:
大部分时候调用 onDraw()方法就是调用invalidate()的结果,所以减少不必要的调用invalidate()方法。有可能的,调用四种参数不同类型的invalidate(),而不是调用无参的版本。无参变量需要刷新整个view,而四种参数类型的变量只需刷新指定部分的view.这种高效的调用更加接近需求,也能减少落在矩形屏幕外的不必 要刷新的页面。

ii> 优化layout

任何时候执行requestLayout(),会使得Android UI系统去遍历整个View的层级来计算出每一个view的大小。如果找到有冲突的值,它会需要重新计算好几次。
尽量保持View的层级是扁平化:提高效率。
对于复杂的UI,用自定义的ViewGroup来执行他的layout操作。与内置的view不同,自定义的view可以使得程序仅仅测量这一部分,这避免了遍历整个view的层级结构来计算大小。

②使用硬件加速

作为Android3.0,Android2D图表系统可以通过大部分新的Android装置自带GPU(图表处理单元)来增加,对于许多应用程序 来说,GPU硬件加速度能带来巨大的性能增加,但是对于每一个应用来讲,并不都是正确的选择。Android框架层更好地为你提供了控制应用程序部分硬件 是否增加的能力。

手机GPUs非常擅长某些任务,例如测量,翻转,和平移位图类的图片。
不擅长其他的任务:例如画直线和曲线。
为了利用GPU加速度类,应该增加GPU擅长的操作数量,和减少GPU不擅长的操作数量

③初始化时创建对象

不要在onDraw方法内创建绘制对象,一般都在构造函数里面初始化对象;

④状态的存储与恢复

如果内存不足,而恰好我们的Activity置于后台,不幸被重启,或者用户旋转屏幕造成Activity重启,我们的View应该也能尽可能的去保存自己的属性。

8,常用方法

1)根据屏幕大小,设置图片高度

如:图片高度为140px

    WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    float height = (display.getWidth() * 140) / 720;

    ViewGroup.LayoutParams params = rl_background.getLayoutParams();
    params.height = (int) height;
    rl_background.setLayoutParams(params);

或者

LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(display.getWidth(), (int)height);
cycleViewPager.setLayoutPams(layoutParams);

2)控件透明度设置

①java:
setAlpha()的括号中可以填0–255之间的数字。数字越大,越不透明。

text = (TextView) findViewById(R.id.text);
text.getBackground().setAlpha(12);

②xml中:
值为0~1之间的数。数字越大,越不透明。1表示完全不透明,0表示完全透明。

android:alpha="0.5"

③直接颜色给半透明
20000000 整体给00000000。前两位表示透明度。

9,性能优化

尽量减少布局文件的层级(这样Android绘制时的工作量少了)。防止过度绘制,做布局优化:

1)删除布局中无用的控件和层级

2)有选择地使用性能高的ViewGroup

如果LinearLayout和RelativeLayout二选一,选择LinearLayout。因为RelativeLayout功能比较复杂,布局需要话费更多的CPU时间。

LinearLayout和FrameLayout都是简单高效的ViewGroup。
如果需要通过嵌套的方式完成布局,则增加了布局的层级,用RelativeLayout更好。

3)用<include>标签、<merge>标签、ViewStub

①使用include复用布局文件,使用merge标签避免嵌套布局

<include>用于布局重用,与<merge>搭配使用,可以降低布局的层级。
ViewStub提供了按需加载的功能,当需要时才会将ViewStub中的布局加载到内存,提高了程序初始化的效率。

<include>用法

在要添加该include布局文件的xml中添加如下控件:

<include layout="@layout/titlebar"/>

注意:
这个标签只支持layout_开头的属性,android:layout_width,其他属性android:id都不支持。

<merge>用法

<include>一起使用,减少布局层级。
如当前布局是一个竖直方向的LinearLayout,这时如果<include>的布局文件也是竖直方向的LinearLayout,那么<include>中的LinearLayout是多余的,通过<merge>可去掉多余的一层LinearLayout。
include布局文件这样写:

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/one"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/two"/>
</merge>

使用ViewStub仅在需要的时候在展示出来

10,常用View

1)TextView

①设置TextView顶部图片

drawableLeft、drawableRight、drawableTop、drawableBottom

②划线效果

textView.getPaint().setFlags(Paint. UNDERLINE_TEXT_FLAG ); //下划线
textView.getPaint().setAntiAlias(true);//抗锯齿
textview.getPaint().setFlags(Paint. STRIKE_THRU_TEXT_FLAG); //中划线
setFlags(Paint. STRIKE_THRU_TEXT_FLAG|Paint.ANTI_ALIAS_FLAG);  // 设置中划线并加清晰 
textView.getPaint().setFlags(0);  // 取消设置的的划线

③设置行间距

--android:lineSpacingExtra
设置行间距,如8dp。 
--android:lineSpacingMultiplier
设置行间距的倍数。如”1.2” 

④常用属性

--android:autoLink
当文本为URL链接/email/电话号码/map时,文本显示是否为可点击的链接。可选值(none/web/email/phone/map/all) 
--android:linksClickable
设置链接是否点击连接,即使设置了autoLink。 
--android:textColorLink
文字链接的颜色。
--android:maxLength
限制显示的文本长度,超出部分不显示。
--android:typeface
设置文本字体,必须是以下常量值之一:normal 0, sans 1, serif 2, monospace(等宽字体) 3] 
--android:bufferType
指定getText()方式取得的文本类别。选项editable 类似于StringBuilder可追加字符,也就是说getText后可调用append方法设置文本内容。spannable 则可在给定的字符区域使用样式。
--android:ellipsize
设置当文字过长时,该控件该如何显示。有如下值设置:
start:省略号显示在开头;
end:省略号显示在结尾;
middle:省略号显示在中间; 
marquee:以跑马灯的方式显示(动画横向移动) 
--android:includeFontPadding
设置文本是否包含顶部和底部额外空白,默认为true。 
--android:ems
设置TextView的宽度为N个字符的宽度。
--android:maxEms
设置TextView的宽度为最长为N个字符的宽度,超出会换行。与ems同时使用时覆盖ems选项。  
--android:marqueeRepeatLimit
在ellipsize指定marquee的情况下,设置重复滚动的次数,当设置为marquee_forever时表示无限次。 
--android:scrollHorizontally
设置文本超出TextView的宽度的情况下,是否出现横拉条。 
--android:shadowColor
指定文本阴影的颜色,需要与shadowRadius一起使用。 
--android:shadowDx
设置阴影横向坐标开始位置。 类似有:android:shadowDy
--android:shadowRadius
设置阴影的半径。设置为0.1就变成字体的颜色了,一般设置为3.0的效果比较好。 
--android:textStyle
设置字形[bold(粗体) 0, italic(斜体) 1, bolditalic(又粗又斜) 2] 可以设置一个或多个,用“|”隔开 
--android:textAppearance
设置文字外观。如"?android:attr/textAppearanceLargeInverse"这里引用的是系统自带的一个外观,?表示系统是否有这种外观,否则使用默认的外观。可设置的值如下:
textAppearanceButton/textAppearanceInverse/textAppearanceLarge/textAppearanceLargeInverse/textAppearanceMedium/textAppearanceMediumInverse/textAppearanceSmall/textAppearanceSmallInverse 
--android:textColorHighlight
被选中文字的底色,默认为蓝色 
--android:textScaleX
设置文字之间间隔,默认为1.0f。 

2)Button

// 模拟点击事件
btn1.performClick();
//button去掉样式
 android:background="@null"

3)EditText

4)弹框

Toast

Dialog

构造对话框:

AlertDialog.Builder builder = new AlertDialog.Builder(context);

ProgressDialog dialog = new ProgressDialog(context);

6)progressBar(进度条)

7)ProgressDialog(进度提示框)

就是在AlterDialog上添加Progress, 不需要在xml中进行配置,直接在代码中进行生成即可。
如下例子,在按钮点击的委托代理方法中添加的ProgressDialog,点击按钮时就显示ProgressDialog。

    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.click_button:

                ProgressDialog myProgressDialog = new ProgressDialog(MainActivity.this);
                myProgressDialog.setTitle("ProgressDialog");
                myProgressDialog.setMessage("Loading……");
                myProgressDialog.setCancelable(true);
                myProgressDialog.show();

                break;
            default:
                break;
        }
    }

8)webView(网络视图)

9)SurfaceView

①概念

从Android 1.0(API level 1)时就有,继承自类View。
与普通View不同的是,它有自己的Surface。SurfaceView中采用了双缓存技术,在单独的线程中更新界面,而View在UI线程中更新界面

一般的Activity包含的多个View会组成View hierachy的树形结构,只有最顶层的DecorView,也就是根结点视图,才是对WMS可见的。

AMS统一调度所有应用程序的Activity
WMS控制所有Window的显示与隐藏以及要显示的位置

②用SurfaceView来实现动画

因为View的绘图存在以下缺陷:

View缺乏双缓冲机制
当程序需要更新View上的图像时,程序必须重绘View上显示的整张图片
新线程无法直接更新View组件

③SurfaceView的绘图机制

调用SurfaceView的getHolder()方法即可获得SurfaceView关联的SurfaceHolder。

SurfaceHolder提供了如下方法来获取Canvas对象:
①Canvas lockCanvas()
锁定整个SurfaceView对象,获取该Surface上的Canvas
②Canvas lockCanvas(Rect dirty)
锁定SurfaceView上Rect划分的区域,获取该Surface上的Canvas
③unlockCanvasAndPost(canvas)
释放绘图、提交所绘制的图形,需要注意,当调用SurfaceHolder上的unlockCanvasAndPost方法之后,该方法之前所绘制的图形还处于缓冲之中,下一次lockCanvas()方法锁定的区域可能会“遮挡”它

⑧GLSurfaceView

概念

Android 1.5(API level 3)加入,作为SurfaceView的补充。
它可以看作是SurfaceView的一种典型使用模式。在SurfaceView的基础上,它加入了EGL的管理,并自带了渲染线程。另外它定义了用户需要实现的Render接口,提供了用Strategy pattern更改具体Render行为的灵活性。作为GLSurfaceView的Client,只需要将实现了渲染函数的Renderer的实现类设置给GLSurfaceView即可。

OpenGL即Open Graphics Library(开放的图形库接口),主要用于三维图形编程。
OpenGL ES:OpenGL的子集,嵌入式开放图形库接口。OpenGL ES提供了GLSurfaceView组件。

特性

i>管理一个surface(平面), 这个平面是一个特殊的内存块 , 它可以和 android 视图系统混合 .
ii>管理一个EGL display(EGL 显示) , 它能够让 OpenGL 渲染到一个surface(平面 ).
iii>接受一个用户提供的实际显示的Renderer 对象 .
iv>使用一个专用线程去渲染从而和UI 线程解耦 .
v>支持on-demand 和连续的渲染.
vi>可选的包, 追踪 和 / 或者错误检查这个渲染器的 OpenGL 调用 .

10)RemoteView

①概念

RemoteView是用来描述一个垮进程显示的view。
它inflate于layout资源文件。并且提供了可以修改过view内容的一些简单基础的操作。

②场景

AppWidget
Notification

11)NavigationView(导航菜单、侧拉菜单)

Android5.0推出。

12)ScrollView(滚动视图)

①概念

由FrameLayout派生而来,需要在其上放置有自己滚动内容的子元素。
ScrollView用于设置垂直滚动条;
HorizontalScrollView用于设置水平滚动条。

②特点

scrollView只能有一个孩子,否则会报错:ScrollView can host only one direct child.
scrollView和HorizontalScrollView可以互相嵌套

③举例

<?xml version="1.0" encoding="utf-8"?>  
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent" >  

    <ScrollView  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content" >  

        <LinearLayout  
            android:layout_width="fill_parent"  
            android:layout_height="wrap_content"  
            android:orientation="vertical" >  

            <TextView  
                android:layout_width="fill_parent"  
                android:layout_height="wrap_content"  
                android:text="@string/hello"  
                android:textSize="90sp" />  


        </LinearLayout>  
    </ScrollView>  

</HorizontalScrollView>  

④ScrollView嵌套LinearLayout布局不能撑满全屏的问题

当ScrollView里的元素想填满ScrollView时,使用”fill_parent”或者”match_parent”是不管用的,必需为ScrollView设置:android:fillViewport=”true”。

⑤初始ScrollView自动滚动到底部问题

在ScrollView子标签LinearLayout里面加上:

android:focusable="true"  
android:focusableInTouchMode="true" 

12)spinner列表

13)ListView列表

14)android.view.ViewStub

15)CheckBox(复选按钮)

双状态(选中或不选中)按钮,可添加如下监听:setOnClickListener。

checkBtn.setChecked(true);//指定默认值
checkBtn.isChecked();//判定是否选中

16)RadioGroup和RadioButton

①概念

RadioGroup用于创建一组互斥的单选按钮,只能选中一个。
初始状态下,所有的单选按钮都未选中。

②实现

<RadioGroup android=……>
    <RadioButton  android=……></RadioButton>
    <RadioButton  android=……></RadioButton>
</RadioGroup>
radioBtn1 = ……
radioBtn2 = ……
rg = (RadioGroup)findViewById(……);
rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener(){

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId){
        if(radioBtn1.getId() == checkedId){
        }else{}
    }
}

可以通过rg.clearCheck()清除选中。

③样式

RadioButton去掉默认样式的小圆点

 android:background="@null"

17)AutoCompleteTextView

AutoCompleteTextView类似与百度搜索框,输入信息后会弹出提示相关内容,用户可以从下拉菜单中选择一项以完成输入。
MultiAutoCompleteTextView继承了AutoCompleteTextView,能够对用户输入的文本进行有效的扩充提示,而不需要用户输入整个内容。用户必须提供一个MultiAutoCompleteTextView.Tokenizer以区分不同的子串。

18)ToggleButton(开关按钮)

有两种状态:选中和未选中,需要为不同状态设置不同的显示文本(ON OFF)。

--android:checked   设置按钮是否被选中
--android:textOff   没有被选中时显示的文本
--android:textOn    被选中时显示的文本
--setOnCheckedChangeListener    选中状态发生改变时的动作

19)AnalogClock和DigitalClock(时钟控件)

AnalogClock显示模拟时钟,只显示时针和分针。
DigitalClock显示数字时钟,可精确到秒。

20)DatePicker(日期选择器)、TimePicker(时间选择器)

DatePicker用于选择年月日的布局视图。
TimePicker用于选择一天中时间的视图。

21)ImageSwitch(图像切换器)、Gallery(画廊视图)

①ImageSwitch
是Android中控制图片展示效果的一个控件,如幻灯片效果。
需要设置ImageSwitch.ViewFactory,通常实现一个makeView方法,该方法返回一个ImageView,由ImageSwitch负责显示。
②Gallery
与Spinner有共同的父类。区别在于:
Spinner是垂直的列表选择框,Gallery是水平的。

22)GridView(网络视图)

用于在界面上按行、列分布的方式显示多个控件,类似于ListView。

23)ZoomButton和ZoomControls(缩放按钮)

ZoomButton允许自定义样式,显示的只能是图片,没有Text属性。
ZoomControls是一个包含放大、缩小按钮的控件。

24)TextSwitcher(文字交换器)

仅仅包含类型TextView,用来使屏幕上的Label产生动画效果。
调用setText时,TextSwitcher使用动画方式更换当前文字内容。

25)TabHost和TabActivity

①TabHost

该标签控件提供选项卡(Tab页)的窗口视图容器,是一种特殊的FrameLayout布局。

包含两个子对象:
用户可以选择指定Tab页的标签;
FrameLayout:用来显示内容。

②TabActivity

继承自Activity,其内部定义了TabHost,可以通过getTabHost获取。

26)ImageView(图片视图)

android:src 设置一张图片。
android:scaleType  缩放图片的边界,用于视图边界的选取设定。

27)Menu

实现最容易的方法是通过引用res资源下的menu资源:
在res目录下创建Menu文件,然后创建xml_menu.xml资源:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:id="">
        <item android:id="" android:title=""/>
        <item android:id="" android:title=""/>
    </group>
</menu>
@Override
public boolean onCreateOptionsMenu(Menu menu){
    //menu.add("");
    MenuInflaterinflater = getMenuInflater();
    inflater.inflate(R.menu.xml_menu, menu);
    return true;
}

当每次Menu显示时,会调用方法onPrepareOptionsMenu,也可以在菜单每次被调用时,对菜单中的项重新生成,通过重载onPrepareOptionsMenu来实现,由于每次调用时都要重新生成,对于那些不经常变化的菜单,效率就会比较低。

调用Menu.addSubMenu()方法,为某个菜单项添加子菜单。

①选项菜单Options menus

一个Activity只能有一个选项菜单,在按下Menu键时,显示在屏幕下方。

重写 onCreateOptionsMenu 用以创建选项菜单 ;
重写 onOptionsItemSelected 用以响应选项菜单 。

②上下文菜单Context menus

为Activity中的任何一个视图注册一个上下文菜单,“长按”出现。

重写 onCreateContextMenu 用以创建上下文菜单;
重写 onContextItemSelected 用以响应上下文菜单 。

③弹出式菜单Popup menus

依赖于Activity中的某个一个视图。

④sub Menu

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值