Android 开发入门(2)
0x04 简单控件
(1)文本显示
a. 添加文本
设置文本内容主要有两种方式:
-
XML:通过属性
android:text
设置-
在 layout 目录下新建 activity_text_view.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_ha" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="你好,安卓" /> </LinearLayout>
-
-
Java:通过调用文本视图对象(TextView)的
setText()
方法设置-
在 java/(package) 下新建 TextViewActivity.java
package com.example.myapplication; import android.os.Bundle; import android.widget.TextView; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; public class TextViewActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_text_view); TextView tv_ha = findViewById(R.id.tv_ha); tv_ha.setText("你好,世界"); } }
-
特别的,可以将需要添加的文本内容统一设置在 res/values/string.xml 中,在 XML 中通过
text="@string/***"
获取,在 Java 中通过setText(R.string.***)
获取
b. 字体大小
设置文本大小主要有两种方式:
-
XML:通过属性
android:textSize
设置需要设置的单位:
- px:手机屏幕最小显示单位,与设备显示屏有关
- dp:与屏幕尺寸有关
- sp:专门用于设置字体大小,在系统设置中可以调整字体大小
<TextView android:textSize="20px"></TextView>
-
Java:通过调用
setTextSize()
方法设置tv_ha.setTextSize("20");
此时单位由官方设置为 sp
c. 字体颜色
-
XML
-
文本文字颜色:通过属性
android:textColor
设置,格式为 RGB(A) 的十六进制数<TextView android:textColor="#00ff00ff"></TextView> // or <TextView android:textColor="#00ff00"></TextView>
-
文本背景颜色:通过属性
android:background
设置<TextView android:background="@color/green"></TextView>
-
-
Java
-
文本文字颜色:通过调用
setTextColor()
方法设置,可从 Color 类中选色或使用十六进制数tv_ha.setTextColor(Color.GREEN); // or tv_ha.setTextColor(0xFF00FF00); // 前两位为透明度 // or tv_ha.setTextColor(0x00FF00); // 不包含透明度
-
文本背景颜色:通过调用
setBackgroundColor()
方法设置tv_ha.setBackgroundColor(Color.GREEN) // 从 Java 的 Color 类选色 tv_ha.setBackgroundColor(R.color.green) // 从 XML 的 color 类中选色
-
(2)视图基础
a. 宽高
-
XML:通过属性
android:layout_width
/android:layout_height
设置宽/高共三种取值:
match_parent
:与父视图一致wrap_content
:与内容自适应- 以
dp
为单位的数值
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="300dp"></LinearLayout>
-
Java:在 XML 中设置其宽高为
wrap_content
的前提下,- 调用控件对象的
getLayoutParams()
方法,获取该控件的布局参数 - 修改宽(
width
)高(height
)属性的参数 - 调用控件对象的
setLayoutParams()
方法,设置修改后的布局参数
// ... import android.view.ViewGroup; public class TextViewActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { // ... ViewGroup.LayoutParams params = tv_ha.getLayoutParams(); params.width = 20; // 单位为 px params.height = 40; tv_ha.setLayoutParams(params); } }
对于宽高单位从 dp 向 px 的转换,可以通过以下方法实现:
// (package)目录下添加 utils 软件包,新建 dp2px.java 文件,内容如下: package com.example.myapplication.utils; import android.content.Context; public class dp2px { public static int d2p(Context context, float dpValue) { float scale = context.getResources().getDisplayMetrics().density; return (int)(dpValue * scale + 0.5f); // 0.5f 用于四舍五入 } }
// 在对应 (Activity).java 文件中引用上述代码 // ... import com.example.myapplication.utils.dp2px; public class TextViewActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { // ... params.width = dp2px.d2p(this, 300); // ... } }
- 调用控件对象的
b. 边距
-
XML
- 通过属性
android:layout_margin
设置外边距 - 通过属性
android:padding
设置内边距
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="300dp" android:padding="60dp"> </LinearLayout>
- 通过属性
c. 对齐
-
XML
- 通过属性
android:layout_gravity
设置外对齐 - 通过属性
android:gravity
设置内对齐
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="left" android:gravity="top|right"> </LinearLayout>
- 通过属性
(3)常用布局
a. 线性布局 LinearLayout
- 通过属性
android:orientation
设置排列方向:水平(horizontal)/垂直(vertical) - 通过属性
android:layout_weight
设置布局权重android:layout_width="0dp"
:此时权重为宽度比例android:layout_height="0dp"
:此时权重为高度比例
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:background="#ff0000"
android:textColor="#ffffff"
android:text="横向第一项" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center"
android:background="#ff0000"
android:textColor="#ffffff"
android:text="横向第二项" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:layout_gravity="center"
android:background="#00ff00"
android:textColor="#ffffff"
android:text="竖向第一项" />
<TextView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:layout_gravity="center"
android:background="#00ff00"
android:textColor="#ffffff"
android:text="竖向第二项" />
</LinearLayout>
</LinearLayout>
b. 相对布局 RelativeLayout
- 相对布局的下级视图位置由其他视图决定,用于确定下级视图位置的参照物分为
- 与该视图自身平级的视图
- 该视图的上级视图
- 若未设置,则默认为左上角
相对位置取值 | 相对位置说明 |
---|---|
android:above="@id/xxxxx" |
当前视图在指定视图的上边 |
android:toLeftOf="@id/xxxxx" |
当前视图在指定视图的左边 |
android:toRightOf="@id/xxxxx" |
当前视图在指定视图的右边 |
android:below="@id/xxxxx" |
当前视图在指定视图的下边 |
android:alignTop="@id/xxxxx" |
当前视图在指定视图的上对齐 |
android:alignLeft="@id/xxxxx" |
当前视图在指定视图的左对齐 |
android:alignRight="@id/xxxxx" |
当前视图在指定视图的右对齐 |
android:alignBottom="@id/xxxxx" |
当前视图在指定视图的下对齐 |
android:layout_centerInParent="true" |
当前视图在上级视图的中间 |
android:layout_centerHorizontal="true" |
当前视图在上级视图的水平居中 |
android:layout_centerVertical="true" |
当前视图在上级视图的垂直居中 |
android:alignParentTop="true" |
当前视图在上级视图的上对齐 |
android:alignParentLeft="true" |
当前视图在上级视图的左对齐 |
android:alignParentRight="true" |
当前视图在上级视图的右对齐 |
android:alignParentBottom="true" |
当前视图在上级视图的下对齐 |
c. 网格布局 GridLayout
- 支持多行多列的表格排列
- 默认从左往右、从上往下排列,含有以下属性
columnCount
属性:指定网格列数rowCount
属性 :指定网格行数
- 可以通过设置权重属性
layout_columnWeight
或layout_rowWeight
进行行列填充调整
d. 滚动视图 ScrollView
-
垂直滚动视图:
ScrollView
<ScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> </ScrollView>
-
水平滚动视图:
HorizontalScrollView
<HorizontalScrollView android:layout_width="wrap_content" android:layout_height="match_parent"> </HorizontalScrollView>
(4)按钮触控
a. 控件 Button
控件 Button 由 TextView 派生而来,有一定的区别
-
有默认的按钮背景
-
内部文本默认居中对齐
-
默认将小写字母转为大写
-
textAllCaps
属性:指定是否将英文字母转为大小写,true/false- 保持原状:
android:textAllCaps="false"
- 保持原状:
-
onClick
属性:接管用户点击动作,可设置触发的方法-
XML
<Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="获取时间" android:textColor="@color/black" android:textSize="20sp" android:textAllCaps="false" android:onClick="aClickEvent" /> <TextView android:id="@+id/tv_res" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textColor="@color/black" android:textSize="20sp" />
-
Java
-
utils/getDateString.java
package com.example.myapplication.utils; import java.text.SimpleDateFormat; import java.util.Date; public class getDateString { public static String getNowTime() { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); return sdf.format(new Date()); } }
-
MainActivity.java
package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.example.myapplication.utils.getDateString; public class MainActivity extends AppCompatActivity { private TextView tv_res; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_res = findViewById(R.id.tv_res); } public void aClickEvent(View view) { String str = String.format("%s:现在时间%s", ((Button)view).getText(), getDateString.getNowTime()); tv_res.setText(str); } }
-
-
b. 点击事件和长按事件
XML:
<Button
android:id="@+id/btn_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="获取时间"
android:textColor="@color/black"
android:textSize="20sp"
android:textAllCaps="false" />
<TextView
android:id="@+id/tv_res"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/black"
android:textSize="20sp" />
监听器:用于监听控件的动作行为,只有控件发生了指定的动作,监听器才会触发并执行
-
点击监听器:
setOnClickLintener()
方法设置,当按钮被按住的时间少于 500 毫秒时会触发public class MainActivity extends AppCompatActivity { private TextView tv_res; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_res = findViewById(R.id.tv_res); findViewById(R.id.aClickEvent).setOnClickListener(new AOnClickEvent(tv_res)); } static class AOnClickEvent implements View.OnClickListener { private final TextView tv_res; // 构造函数 public AOnClickEvent(TextView tv_res) { this.tv_res = tv_res; } @Override public void onClick(View view) { // 通过判断 id 确认执行项目,实现简单函数复用 if (view.getId() == R.id.btn_time) { String str = String.format("%s:现在时间%s", ((Button)view).getText(), getDateString.getNowTime()); tv_res.setText(str); } } } }
-
长按监听器:
setOnLongClickLintener()
方法,当按钮被按住的时间超过 500 毫秒时会触发findViewById(R.id.aClickEvent).setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { String str = String.format("%s:现在时间%s", ((Button)view).getText(), getDateString.getNowTime()); tv_res.setText(str); return true; } }); }
对于上述写法涉及了匿名内部类的概念,可以用 lambda 写法替换,如:
findViewById(R.id.aClickEvent).setOnLongClickListener(view -> { String str = String.format("%s:现在时间%s", ((Button)view).getText(), getDateString.getNowTime()); tv_res.setText(str); return true; });
c. 禁用和恢复按钮
-
在实际情况中,按钮通常有两种类型:
- 不可用按钮:不允许点击,点击时无事件触发,文字灰色
- 可用按钮:允许点击,点击时触发事件,文字颜色正常
-
是否允许点击由
enable
属性控制,其值为true
时允许点击,值为false
时不允许 -
XML:
android:enable="true"
-
Java:
findViewById(R.id.xxxxx).setEnable(true)
(5)图像显示
a. 图像视图 ImageView
图像视图通常位于 res/drawable*** 目录
XML 中的缩放类型 | Java ScaleType 类的缩放类型 | 说明 |
---|---|---|
fitXY | FIT_XY | 图片填充 |
fitStart | FIT_START | 保持宽高比,位于视图上方/左侧 |
fitCenter | FIT_CENTER | 保持宽高比,位于视图中间 |
fitEnd | FIT_END | 保持宽高比,位于视图下方/右侧 |
center | CENTER | 保持图片原尺寸,并使其位于视图中间 |
centerCrop | CENTER_CROP | 拉伸图片使其充满视图,并位于视图中间 |
centerInside | CENTER_INSIDE | 保持宽高比,缩小图片使其位于视图中间 |
-
XML:通过
android:src="@drawable/pictureName"
属性设置<ImageView android:id="@+id/iv" android:layout_width="match_parent" android:layout_height="220dp" android:src="@drawable/ic_launcher_background" android:scaleType="fitCenter" />
-
Java:通过调用
setImageResource(R.drawable.pictureName)
方法设置// ... import android.widget.ImageView; // ... ImageView iv = findViewById(R.id.iv); iv.setImageResource(R.drawable.ic_launcher_background); iv.setScaleType(ImageView.ScaleType.FIT_CENTER);
b. 图像按钮 ImageButton
控件 ImageButton 由 ImageView 派生而来,有一定的区别
- 与 Button 相比,ImageButton
- 只能显示图片
- 可按比例缩放
- 可分别在前景和背景显示图片,从而事项两张图片的叠加效果
- 适合表达特殊字体或公式等
- 与 ImageView 相比,ImageButton
- 有默认的按钮背景
- 默认缩放类型为 center
c. 图像与文本结合
- 利用 LinearLayout 对 ImageView 和 TextView 组合布局
- 利用 Button 的
android:drawableXxx
属性设置文本周围的图标android:drawableTop
:指定文字上方的图片android:drawableLeft
:指定文字左侧的图片android:drawableRight
:指定文字右侧的图片android:drawableBottom
:指定文字下方的图片android:drawablePadding
:指定文字与图片的间距