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

64 阅读2分钟

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

UI组件

什么是 Android UI

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

UI组件

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

常规View的属性和方法img

UI组件间的关系

imgimg

布局

LinearLayout

示例:

 <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>

img

RelativeLayout

示例 :

 <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>

img

FrameLayout

示例:

 <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>

img

ConstraintLayout

示例:

 <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>

img

布局总结

img

渲染

布局加载

在Activity中设置布局文件

 TextView textView;
 ​
 @Override
 public void onCreate(Bundle savedInstanceState) {  
     // call the super class onCreate to complete the creation of activity like    
     // the view hierarchy    
     super.onCreate(savedInstanceState);  
   
      // set the user interface layout for this activity  
      // the layout file is defined in the project res/layout/main_activity.xml file
     setContentView(R.layout.main_activity);   
 ​
      // initialize member TextView so we can manipulate it later   
     textView = (TextView) findViewById(R.id.text_view);
 }

setContentView最终创建了DecorView,并由LayoutInflater来加载了XML文件

 @Override
 public void setContentView(int resId) {
     ensureSubDecor();
     ViewGroup contentParent = (ViewGroup) mSubDecor
     .findViewById(android.R.id.content);
     contentParent.removeAllViews();
     LayoutInflater.from(mContext).inflate(resId, contentParent);
     mOriginalWindowCallback.onContentChanged();
 }

布局解析

布局加载后调用了LayoutInflater相关方法,LayoutInflater解析了XML文件,并根据XML文件生成了View实例,并将View实例添加了到了其ViewGroup中

 void rInflate(XmlPullParser parser, View parent, Context context,AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
     while (((type = parser.next()) != XmlPullParser.END_TAG||
             parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
             // 省略
             // 核心代码
             final View view = createViewFromTag(parent, name, context, attrs);
             final ViewGroup viewGroup = (ViewGroup) parent;
             final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
             rInflateChildren(parser, view, attrs, true);
             viewGroup.addView(view, params);
     }
 }

布局渲染

页面绘制流程

img

UI渲染流程

img

渲染流程img

交互

常用交互事件监听器

img

触摸事件

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

img

捕获触摸事件

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

代码如下:

     public class MainActivity extends Activity {
         @Override
         public boolean onTouchEvent(MotionEvent event){
             int action = MotionEventCompat.getActionMasked(event);
             switch(action) {
                 case (MotionEvent.ACTION_DOWN) :
                     Log.d(DEBUG_TAG,"Action was DOWN");
                     return true;
                 case (MotionEvent.ACTION_MOVE) :
                     Log.d(DEBUG_TAG,"Action was MOVE");
                     return true;
                 case (MotionEvent.ACTION_UP) :
                     Log.d(DEBUG_TAG,"Action was UP");
                     return true;
                 case (MotionEvent.ACTION_CANCEL) :
                     Log.d(DEBUG_TAG,"Action was CANCEL");
                     return true;
                 case (MotionEvent.ACTION_OUTSIDE) :
                     Log.d(DEBUG_TAG,"Movement occurred outside bounds " + "of current screen element");
                     return true;
                 default :
                     return super.onTouchEvent(event);
         }
     }

事件处理流程

img

交互总结

img

\