2. 跟随手指的小球
功能:画一个小球,可以跟随手指在屏幕上移动。
自定义一个UI组件
DrawView.java
package com.example.aimee.ballfollowfinger; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; public class DrawView extends View { public float currentX = 40; public float currentY = 50; //定义并创建画笔 Paint p = new Paint(); public DrawView(Context context) { super(context); } public DrawView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //设置画笔的颜色 p.setColor(Color.RED); //绘制一个小圆(作为小球) canvas.drawCircle(currentX,currentY,15,p); } //为该组件的触碰事件重写事件处理方法 @Override public boolean onTouchEvent(MotionEvent event) { //修改currentX,currentY两个属性 currentX = event.getX(); currentY = event.getY(); //通知当前组件重绘自己 invalidate(); //返回true表明该处理方法已经处理该事件 return true; } }
自定义组件后,有两种方法实现,第一种是直接放在layout布局里,第二种是在Activity添加。
首先讲动态添加
MainActivity.java
package com.example.aimee.ballfollowfinger; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.LinearLayout; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获取布局文件中的LinearLayout容器 LinearLayout root = (LinearLayout) findViewById(R.id.root); //创建DrawView组件 final DrawView draw = new DrawView(this); //设置自定义组件的最小宽度、高度 draw.setMinimumWidth(300); draw.setMinimumHeight(500); root.addView(draw); } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:orientation="vertical"> </LinearLayout>
其次说在布局文件中添加
MainActivity.java
package com.example.aimee.ballfollowfinger; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.LinearLayout; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // //获取布局文件中的LinearLayout容器 // LinearLayout root = (LinearLayout) findViewById(R.id.root); // //创建DrawView组件 // final DrawView draw = new DrawView(this); // //设置自定义组件的最小宽度、高度 // draw.setMinimumWidth(300); // draw.setMinimumHeight(500); // root.addView(draw); } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:orientation="vertical"> <com.example.aimee.ballfollowfinger.DrawView android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
布局管理器:
为了更好地管理Android应用的用户界面里的各组件,Android提供了布局管理器。通过使用布局管理器,Android应用的图形用户界面具有良好的平台无关性。通常来说,推荐使用布局管理器来管理组件的分布、大小,而不是直接设置组件位置和大小。例如,通过如下代码定义了一个文本框(TextView):
TextView hello = new TextView(this); hello.setText("Hello Android!“);
为了让这个组件在不同手机屏幕上都能运行良好——不同手机屏幕的分辨率、尺寸并不完全相同,如果让程序手动控制每个组件的大小、位置,则将给编程带来巨大的困难。为了解决这个问题,Android提供了布局管理器。布局管理器可以根据运行平台来调整组件的大小,程序员要做的,只是为容器选择合适的布局管理器。
所有的布局管理器都是ViewGroup的子类。
TableLayout-->LinearLayout-->ViewGroup-->View
AbsoluteLayout-->ViewGroup-->View
FrameLayout-->ViewGroup-->View
GridLayout->ViewGroup-->View
RelativeLayout->ViewGroup-->View
所有布局都可作为容器类使用,因此可以调用多个重载addView()向布局管理器中添加组件。实际上,我们完全可以用一个布局管理器嵌套到其它布局管理器中——因为布局管理器也继承了View,也可以作为普通UI组件使用。
1.线性布局
线性布局由LinearLayout类来代表,线性布局会将容器里的组件一个挨着一个地排列起来。LinearLayout可以控制各组件横向排列(通过设置android:orientation属性控制),也可控制各组件纵向排列。
Android的线性布局不会换行,当组件一个挨着一个地排列到头之后,剩下的组件将不会被显示出来。
LinearLayout支持的常用XML属性及相关方法的说明。
XML属性和相关方法:
android:baselineAligned——setBaselineAligned(boolean)
该属性设为false,将会阻止该布局管理器与它的子元素的基线对齐
android:divider——setDividerDrawable(Drawable)
设置垂直布局时两个按钮之间的分隔条
android:gravity——setGravity(int)
设置布局管理器内组件的对齐方式。该属性支持top/bottom/left/right/center_vertical/fill_vertical/center_horizontal/fill_horizontal/center/fill/clip_vertical/clip_horizontal几个属性值,也可以同时指定多种对齐方式的组合,例如left|center_vertical代表出现在屏幕左边,而且垂直居中。
android:mesureWithLargestChild——setMesureWithLargestChildEnabled(boolean)
当该属性设为true时,所有带权重的子元素都会具有最大子元素的最小尺寸。
android:orientation——setOrientation(int)
设置布局管理器内组件的排列方式,可以设置为horizontal(水平排列)、vertical(垂直排列,默认值)两个值的其中之一。
LinearLayout包含的所有子元素都受LinearLayout.LayoutParams控制,因此LinearLayout包含的子元素可以额外指定下面的属性。
XML属性:
android:layout_gravity
指定该子元素在LinearLayout中的对齐方式
android:layout_weight
指定该子元素在LinearLayout中所占的权重
提示:基本上很多布局管理器都提供了相应的LayoutParams内部类,该内部类用于控制它们的子元素支持指定android:layout_gravity属性,该属性设置该子元素在父容器中的对齐方式。与android:layout_gravity相似的属性还有android:gravity属性(一般容器才支持指定该属性),android:gravity属性用于控制它所包含的子元素的对齐方式。
2.表格布局
表格布局由TableLayout所代表,TableLayout继承了LinearLayout,因此它的本质依然是线性布局管理器。表格采用行、列的形式来管理UI组件,TableLayout并不需要明确地声明包含多少行、多少列,而是通过添加TableRow、其它组件来控制表格的行数和列数。
每次向TableLayout中添加一个TableRow,该TableRow就是一个表格行,TableRow也是容器,因此它也可以不断地添加其它组件,每添加一个子组件该表格就增加一列。
如果直接向TableLayout中添加组件,那么这个组件将直接占用一行。
在表格布局中,列的宽度由该列中最宽的那个单元格决定,整个表格布局的宽度则取决于父容器的宽度(默认总是占满父容器本身)。
在表格布局管理器中,可以为单元格设置如下3种行为方式。
Shrinkable:如果某个列被设为Shrinkable,那么该列的所有单元格的宽度可以被收缩,以保证该表格能适应父容器的宽度。
Stretchable:如果某个列被设为Stretchable,那么该列的所有单元格的宽度可以被拉伸,以保证组件能完全填满表格空余空间。
Collapsed:如果某个列被设为Collapsed,那么该列的所有单元会被隐藏。
TableLayout继承了LinearLayout,因此它完全可以支持LinearLayout所支持的全部XML属性。除此之外,TableLayout还支持以下XML属性。
XML属性和相关方法
android:collapseColumns——setColumnCollapsed(int,boolean)
设置需要被隐藏的列的列序号。多个列序号之间用逗号隔开
android:shrinkColumns——setShrinkAllColumns(boolean)
设置允许被收缩的列的列序号。多个列序号之间用逗号隔开
android:stretchColumns——setStretchAllColumns(boolean)
设置允许被拉伸的列的列序号。多个列序号之间用逗号隔开
1111