这是我参与「第四届青训营 」笔记创作活动的第5天
UI组件
什么是 Android UI
- UI:User Interface
- Android系统是图形用户界面操作系统
- UI界面由多个不同功能的UI组件构成
- Android SDK提供了大量的UI组件
UI组件
常规UI组件大多由Android Framework中的android.widget这个package提供
常规View的属性和方法
UI组件间的关系
布局
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>
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>
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>
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>
布局总结
渲染
布局加载
在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);
}
}
布局渲染
页面绘制流程
UI渲染流程
渲染流程
交互
常用交互事件监听器
触摸事件
当用户触摸屏幕时,系统建立一系列的MotionEvent对象,MotionEvent包含关于发生触摸的位置和时间等细节信息,MotionEvent对象被传递到相应的捕获函数中,例如onTouchEvent()。
捕获触摸事件
- 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);
}
}
事件处理流程
交互总结
\