安卓开发笔记1
(随手写的,不具有参考价值)
MainActivity.java定义了安卓应用程序入口
res文件夹存放了应用程序运行所需的各种资源,包括动画、图像、布局文件、XML文件、数据资源(如字符串)和原始(raw)文件,下面有layout(各种界面布局的XML文件)、drawble(各种图片)、mipmap(不知道干嘛的)和values(字符串、颜色、样式和数组)文件夹。
页面布局用XML文件来完成,一个典型的XML文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
|
assert文件夹也是放各种资源,但与res文件夹不同的是,res文件夹的内容会在程序启动时被加载进内存里,而assert文件夹则不会。所以assert文件夹里会放一些比较大的资源文件。
Android程序必须在根目录下包含一个 AndroidManifest.xml文件。 Androidmanifest.xml定义了应用程序的整体布局、提供的内容与动作,还描述了程序的信息,包括应用程序的包名、所包含的组件、服务( Service)、接收器( Receiver)、应用程序兼容的最低版本、图标、应用程序自身应该具有的权限的声明以及其他应用程序访问该应用程序时应该具有的权限等。它是应用程序的重要组成文件。
Android应用程序由Activity、Activity Manager 、 ContentProvider、Service、BroadcastReceiver等部分组成。
Activity用于与用户交互,它有各种Widget组件,如按钮Button、列表List和文本框TextBox。一个程序一般包括多个Activity。
顾名思义,ContentProvider是提供内容的。一个应用程序使用的数据是不能被其他程序访问的。当需要共享数据时,ContentProvider提供了程序之间数据交换的机制。
Service是与 Activity独立且可以保持后台运行的服务,相当于一个在后台运行的没有界面的 Activity。如果应用程序并不需要显示交互界面但却需要长时间运行,就需要启用Service。
BroadcastReceiver用于应用程序间传递信息。
Intent用于连接以上组件,并在它们之间传递信息。
activity
Activity是 Android程序的呈现层,显示可视化的用户界面,并接收与用户交互所产生的界面事件。 Android应用程序可以包含一个或多个 Activity,一般在程序启动后会首先呈现一个主 Activity,用于提示用户程序已经正常启动并显示一个初始的用户界面。
可以把Activity理解为用户界面。
项目创建时,系统会自动创建一个MainActivity,作为程序启动后的第一个界面,根据需要可以从这个Activity启动别的Activity
activity有4种状态:活动状态、暂停状态、停止状态和非活动状态。
活动状态就是能被用户看到,能与用户交互;
暂停状态就是界面上被部分遮挡,不能与用户交互;
停止状态就是被完全遮挡;
非活动状态是上述三者以外的状态。
第四章:用户界面设计基础
Android常用布局包括线性布局、表格布局、相对布局、框架布局和绝对布局。
用户界面通过View和ViewGroup来构建。
View对象是 Android平台上表示用户界面的基本单元,一个View占据屏幕上的一块方形区域,存储了该特定区域的布局参数和内容。 Android平台下View类是所有可视化控件的基类,主要提供控件绘制和事件处理的方法。
ViewGroup是由View和其他ViewGroup组成的。
各种布局类的关系如下图:
常用的布局属性
ID属性
一个控件会有一个ID,Java代码中可以根据这个ID来找到相应的控件。
在XML中一般以字符串的形式定义一个ID。如android:id=”@+id/tvHello”。
在Java中可以通过调用 Activity.findviewByld()方法引用相应的ID,并创建这个View对象的实例。
尺寸参数
尺寸参数包括layout_width和layout_length,给出了这个View的大小。它们的值可以是一个具体的数字,如50px;也可以是fill_parent,使它填充尽可能多的空间;还可以是wrap_content,使其恰好能显示其内部的内容
xmlns:android属性
一般取值为”http://schemas.android.com/apk/res/android"。
各种常用布局方式
线性布局
线性布局的子控件定义在<Linearlayout>和</Linearlayout>标签之间。线性布局是最简单的布局之一,它将其包含的 Widget控件元素按水平或者垂直方向顺序排列。
布局方向由属性 orientation的值来决定。同时,使用此布局时可以通过设置控件的 weight参数控制各个控件在容器中的相对大小。
在线性布局中可使用 gravity属性来设置控件的对齐方式。gravity属性的可供取值有top(到容器顶)、bottom(底)、left(左)、 right(右)、 center_vertical(纵向中央)、 center_horizonal(横向中央)、 center(中央)、 fill vertical(纵向拉伸以填满容器)、 fill horizonal(横向拉伸以填满容器)、fill(纵向横向同时拉伸以填满容器)等。当需要为 gravity设置多个属性值时,要用“|”每个属性值隔开。
表格布局
表格布局以<TableLayout>开始,用<TableRow>代表一个行,每个行可以有很多列。如果一个自控件没有在任何<TableRow>中,会单独成一行。
TableLayout中可以设置三种属性:
1.Shrinkable:如果一个列被设置为shrinkable,则该列的宽度可以收缩,以适应其父容器的大小。
2.Stretchable:如果一个列被设置为stretchable,则该列的宽度可以伸长,以填满表格中剩余的空间。
3.Collapsed:如果一个列被设置为collapsed,则该列会被隐藏。
相对布局
相对布局以<RelativeLayout>开始。顾名思义,相对布局就是让自控件的位置有相互依赖关系。
相对布局中, android: layout_centerlnparent属性指定是否位于父控件的中央位置, android:layout_below属性指定位置为在参照控件的下方, android: layout_toRightOf属性指定位置为在参照控件右侧, android: layout_alignBottom属性指定与参照控件底部对齐。还可以用android:marginLeft等具体调整位置。
绝对布局
绝对布局,就是让程序员自己直接指定控件的位置。绝对布局以<AbsoluteLayout>开始。自控件可以通过layout_x和layout_y指定位置。
框架布局
框架布局以<FrameLayout>开始,可以让不同的自控件叠在一起。
Widget控件好像就是各种常用的自控件。常用的Widget控件有TextView、EditView、Button、CheckBox和RadioButton等。
TextView和EditText
TextView用于在屏幕上显示文字信息。EditText用于接受用户从键盘输入的文本信息,是TextView的子类。
TextView可以用textColor来指定颜色,textStyle来指定字体风格,textSize来指定大小,background来指定背景颜色,gravity来指定位置。
EditText可以用hint来给输入的文本框增加提示信息,password来设置是否将输入以密码显示。
可以用style来指定按钮的风格,也可以自己定义其他的风格。
CheckBox
CheckBox是一种可以支持多个选项的控件。一般可以在一个Layout下定义多个CheckBox以供选择。可以设置checked=”true”来将这个选项默认勾选。
RadioGroup和RadioButton用于提供单选按钮。一个RadioGroup下面可以有很多个RadioButton作为选项。RadioButton里同样可以设置checked=”true”来将这个选项默认勾选。
安卓中的事件处理机制
在图形用户界面的开发设计中,有两个非常重要的内容:一个是控件的布局,另一个是控件的事件处理。 Android在事件处理过程中主要涉及3个概念。
(1)事件:表示用户在图形界面的操作的描述,通常是封装成各种类,例如,键盘事件操作相关的类为 Keyevent,触摸屏相关的移动事件类为 Motionevent等。
(2)事件源:事件源是指发生事件的控件,例如, Button、 Edittext等。
(3)事件处理者:事件处理者是指接收事件并对其进行处理的对象,一般是一个实现某些特定接口类的对象
事件的处理方法有两类,即”基于监听接口”和”基于回掉机制”。
基于监听接口的事件处理机制
有三种实现方式:
直接实现接口的处理方式、内部类处理方式和匿名内部类处理方式。
直接实现接口的处理方式
在定义activity时实现接口,这样activity本身就是事件监听器。
处理按钮点击事件时,一般需要调用该按钮实例的setOnClickListener()方法,并把View.OnClickListener对象的实例作为参数传入。一般是在View.OnClickListener的OnClick()方法里处理按钮的单击事件。
代码示例如下:(没有import和package)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class MainActivity extends AppCompatActivity implements View.OnClickListener{ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button MyButton=(Button)findViewById(R.id.btn_normal); MyButton.setOnClickListener(this); } public void onClick(View v){ switch (v.getId()){ case R.id.btn_normal: TextView mytext=(TextView)findViewById(R.id.tv_button); mytext.setText("普通按钮被点击"); } } }
|
内部类处理方式
这种方法需要在activity里再定义一个类,用这个类实现OnClickListener接口,然后让控件绑定到这个类的一个实例上。代码示例如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class MainActivity extends AppCompatActivity{ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button MyButton=(Button)findViewById(R.id.btn_normal); MyButton.setOnClickListener(new MyClickListener()); } class MyClickListener implements View.OnClickListener{ @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_normal: TextView mytext=(TextView)findViewById(R.id.btn_normal); mytext.setText("普通按钮被点击"); break; } } } }
|
匿名内部类处理方式
使用匿名内部类处理方式是一种最常用的方式,因为大部分事件监听器只会被使用一次,所以这种方式更为合适。
代码示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class MainActivity extends AppCompatActivity{ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button MyButton=(Button)findViewById(R.id.btn_normal); MyButton.setOnClickListener(new View.OnClickListener(){ public void onClick(View v) { switch (v.getId()){ case R.id.btn_normal: TextView mytext=(TextView)findViewById(R.id.btn_normal); mytext.setText("普通按钮被点击"); break; } } }); } }
|
基于回调机制的事件处理
回调机制指的是事件被系统捕获后发送到View,View会调用相应的回调方法(如果有的话)进行处理。当某个事件没有被任何View处理时,便会调用activity中的回调方法。
onKeyDown()方法
该方法用于捕获设备键盘被按下的事件,定义如下:
1
| public boolean onKeyDown(int keyCode,KeyEvent event)
|
keyCode是按下的键盘码,event是按键事件对应的对象,包括了各种信息。
返回一个boolean值,如果为true代表了事件已经被完整地处理了,并不希望其他回调方法进行处理,如果为false则相反。
类似的有onKeyUp()方法用来捕获设备键盘被抬起的事件。
onTouchEvent()方法
onTouchEvent()方法用于捕获触摸屏事件并进行处理。定义如下:
1
| public boolean onTouchEvent(MotionEvent event)
|
参数event包含了事件的各种信息,如触摸的位置、类型和时间等。返回值的意义与onKeyDown()方法类似。一个示例程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class MainActivity extends AppCompatActivity{ TextView TxtAction,TxtPosition; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TxtAction=(TextView)findViewById(R.id.tv_action); TxtPosition=(TextView)findViewById(R.id.tv_position); } public boolean onTouchEvent(MotionEvent event){ int Action=event.getAction(); float x=event.getX(); float y=event.getY(); TxtAction.setText("触屏动作:"+Action); TxtPosition.setText("当前坐标"+"("+x+","+y+")"); return true; } }
|
这个程序会捕获触屏位置并显示这个位置的坐标。
直接绑定到标签的事件处理方法
这种方法可以在xml文档里给View设置一个事件处理方法,具体做法是个给View加一个类似于onClick等属性,属性值是一个方法名。然后在activity类里定义这个方法。
一个示例程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tv_button" android:text="" android:hint="请输入:"> </EditText> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn_normal" android:text="普通按钮"> </Button> <Button style="?android:buttonStyleToggle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn_small" android:text="小按钮" android:onClick="buttonClick"> </Button> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tv_action" > </TextView> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tv_position"> </TextView> </LinearLayout>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class MainActivity extends AppCompatActivity{ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void buttonClick(View v){ switch (v.getId()){ case R.id.btn_small: TextView mytext=(TextView)findViewById(R.id.btn_small); mytext.setText("你好,小按钮被点击!"); break; } } }
|
小练习:加法计算器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="horizontal"> <EditText android:layout_width="100dp" android:layout_height="wrap_content" android:id="@+id/et_1" android:text="" android:hint="请输入数字"> </EditText> <TextView android:layout_width="50dp" android:layout_height="wrap_content" android:id="@+id/tv_message" android:textSize="40dp" android:gravity="center" android:text="+"> </TextView> <EditText android:layout_width="100dp" android:layout_height="wrap_content" android:id="@+id/et_2" android:text="" android:hint="请输入数字"> </EditText> <Button android:layout_width="50dp" android:layout_height="wrap_content" android:id="@+id/bt_1" android:textSize="30dp" android:text="="> </Button> <TextView android:layout_width="50dp" android:layout_height="wrap_content" android:text="" android:id="@+id/tv_1"> </TextView> </LinearLayout>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView;
public class MainActivity extends AppCompatActivity { TextView tv_1; EditText et_1,et_2; Button bt_1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_1=findViewById(R.id.tv_1); et_1=findViewById(R.id.et_1); et_2=findViewById(R.id.et_2); bt_1=findViewById(R.id.bt_1); bt_1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Integer in1=new Integer(et_1.getText().toString()); Integer in2=new Integer(et_2.getText().toString()); Integer out1=in1+in2; tv_1.setText(""+out1); } }); } }
|
一点小总结
设计用户界面,首先要在xml文档里定义各种控件,然后在activity类里将它们实例化,然后用各种监听器来与用户交互。值得注意的是RadioGroup.OnCheckedChangeListener与CheckBox.OnCheckedChangeListener不能一起用,要用CompoundButton.OnCheckedChangeListener。
`