常规 & 高级 UI 编程 | 青训营笔记

127 阅读3分钟

常规 & 高级 UI 编程 | 青训营笔记

这是我参与「第四届青训营 」笔记创作活动的第3天

单听理论会很陌生,以下建议自己边学边上手,以便巩固加深印象。并且本节课很多源码不用每行逐步了解,了解思路与线路足矣,有一定能力再去专研。

这节课我将学习到单个UI组件基础以及多个UI组件排版、从静态页面绘制到动态页面的设计、从系统组件应用到自定义组件等多个维度。分为以下几个部分:

  • UI组件:学习Android UI组件相关知识
  • 布局:学习如何将多个UI组件排版成想要的界面
  • 渲染:学习Android UI渲染流程及原理
  • 交互:学习Android常规的交互知识及原理
  • 动画:学习Android动画相关知识
  • 自定义View:学习如何自定义View

UI组件

什么是Android UI


  • UI:User Interface
  • Android系统是图形用户界面操作系统
  • UI界面由多个不同功能的UI组件构成
  • Android SDK提供了大量的UI组件

UI组件


常规UI组件大多由Android Framework中的android.widget这个package提供

image.png

常规View的属性和方法

image.png

UI组件间关系


image.png

image.png

布局

LinearLayout


线性布局,可用android:orientation定义纵向还是横向线性分布

image.png

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:orientation="vertical" > 

    <EditText        
        android:layout_width="match_parent"        
        android:layout_height="wrap_content" />   

    <EditText        
        android:layout_width="match_parent"      
        android:layout_height="wrap_content" />   

    <EditText       
        android:layout_width="match_parent"     
        android:layout_height="0dp"     
        android:layout_weight="1"      
        android:gravity="top" />   

    <Button      
        android:layout_width="100dp"       
        android:layout_height="wrap_content"     
        android:layout_gravity="right" />
</LinearLayout>

image.png

RelativeLayout


相对容器 image.png

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"    android:layout_height="match_parent"
    android:paddingLeft="16dp"    android:paddingRight="16dp" >

    <EditText
        android:id="@+id/name"        
        android:layout_width="match_parent"   
        android:layout_height="wrap_content" />  

     <Spinner        
        android:id="@+id/dates"        
        android:layout_width="0dp"    android:layout_height="wrap_content"  
        android:layout_below="@id/name"    
        android:layout_alignParentLeft="true"       
        android:layout_toLeftOf="@+id/times" />    

    <Spinner        
        android:id="@id/times"        
        android:layout_width="96dp"    android:layout_height="wrap_content"   
        android:layout_below="@id/name" 
        android:layout_alignParentRight="true" />    

    <Button        
        android:layout_width="96dp"    android:layout_height="wrap_content"   
        android:layout_below="@id/times" 
        android:layout_alignParentRight="true"  />
</RelativeLayout>

image.png

FrameLayout


层级布局 image.png

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">

    <TextView
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:gravity="center"
        android:background="@android:color/holo_blue_bright"
        android:text="我是第一层"/>

    <TextView
        android:layout_width="150dp"
        android:layout_height="140dp"
        android:gravity="center"
        android:background="@android:color/holo_green_light"
        android:text="我是第二层"/>

</FrameLayout>

image.png

ConstraintLayout


image.png

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/iv_beauty"
        android:layout_width="100dp"
        android:layout_height="200dp"
        android:scaleType="centerCrop"
        android:src="@drawable/beauty"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/iv_girl"
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:scaleType="centerCrop"
        android:src="@drawable/girl"
        app:layout_constraintBottom_toBottomOf="@+id/iv_beauty"
        app:layout_constraintLeft_toRightOf="@+id/iv_beauty"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

image.png

渲染

布局加载


在Activity中设置布局文件

image.png setContentView究竟做了什么?通过源码分析可知,setContentView最终创建了DecorView,并由LayoutInflater来加载了XML文件

image.png

布局解析


布局加载后调用了LayoutInflater相关方法,那LayoutInflater究竟做了什么?通过源码分析可知,LayoutInflater解析了XML文件,并根据XML文件生成了View实例,并将View实例添加了到了其ViewGroup中

image.png

布局渲染


页面绘制流程

image.png UI渲染流程

image.png 渲染流程

image.png

交互

button例子

image.png 本人习惯用:


    private TextView result;
    private Button disable;
    private Button enable;
    private Button test;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_button_enable);
        enable = findViewById(R.id.btn_enable);
        disable = findViewById(R.id.btn_disable);
        test = findViewById(R.id.btn_test);
        result = findViewById(R.id.result);

        enable.setOnClickListener(this);
        disable.setOnClickListener(this);
        test.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.btn_enable:
                test.setEnabled(true);
                break;
            case R.id.btn_disable:
                test.setEnabled(false);
                break;
            case R.id.btn_test:
                result.setText("点击了按钮");
                break;
        }
    }
}

这样监听繁多时便不会显得很乱很冗杂

常用交互事件监听器


image.png

触摸事件


当用户触摸屏幕时,系统将建立一系列的MotionEvent对象,MotionEvent包含关于发生触摸的位置和时间等细节信息,MotionEvent对象被传递到相应的捕获函数中,例如onTouchEvent()。

image.png

捕获触摸事件


  • Activity和View都有onTouchEvent(),用于处理触摸事件。
  • 当用户触摸屏幕时,会回调触摸视图上的onTouchEvent()。 对于最终被识别为手势的每个轻触事件序列,onTouchEvent() 都会多次被触发。

image.png

事件处理流程


image.png

交互总结


image.png

动画

帧动画


image.png

补间动画


image.png

image.png 差值器示例:

image.png

属性动画


image.png

image.png

动画总结


image.png

自定义View

自定义View事例


自定义View小结