1、Android 布局
1.1、线性布局(LinearLayout)
特点:
- 控件在水平或垂直方向上依次排列。
- 可以通过设置权重(layout_weight)来控制控件在布局中所占的比例,实现灵活的界面设计。
- 易于理解和使用,是Android开发中最基础的布局方式之一。
适用场景:
- 当需要在一行或一列中整齐地排列控件时,如菜单项、按钮组等。
- 当需要按比例分割空间给不同的控件时,如制作一个分割成多个区域的界面。
实际应用与示例代码:
例如,创建一个垂直方向的线性布局,其中包含两个按钮,第一个按钮占据2/3的空间,第二个按钮占据1/3的空间。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:text="Button 1" />
<Button
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Button 2" />
</LinearLayout>
1.2、约束布局(ConstraintLayout)
特点:
- 提供了更灵活的布局方式,允许控件之间建立水平和垂直方向的约束关系。
- 可以通过约束链(Chains)来统一管理一组相关联的控件,实现复杂的布局设计。
- 减少了布局嵌套,提高了布局性能。
适用场景:
- 当界面设计复杂,需要灵活调整控件位置和关系时。
- 当需要优化布局性能,减少布局嵌套层级时。
实际应用与示例代码:
例如,创建一个约束布局,其中包含两个文本视图(TextView),它们水平排列且等宽,同时底部对齐。
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/textView1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Text 1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/textView2"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintWidth_percent="0.5" />
<TextView
android:id="@+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Text 2"
app:layout_constraintBottom_toBottomOf="@id/textView1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/textView1"
app:layout_constraintWidth_percent="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
在这个例子中,我们使用了layout_constraintWidth_percent
来设置两个文本视图的宽度各占父布局的50%,同时使用约束链(通过app:layout_constraintHorizontal_chainStyle="spread"
定义)来确保它们水平等距分布。底部对齐是通过将两个文本视图的layout_constraintBottom_toBottomOf
属性设置为相同值来实现的。
1.3、表格布局(TableLayout)
特点:
- 允许将控件以表格的形式进行排列,具有行和列的概念。
- 可以通过设置行列的属性来调整控件的布局,如合并单元格、设置列宽等。
- 适用于需要整齐划一展示信息的界面设计。
适用场景:
- 当需要以表格形式展示数据时,如成绩单、时间表等。
- 当需要制作类似表单的输入界面时。
实际应用与示例代码:
例如,创建一个两行两列的表格布局,每个单元格中包含一个文本视图。
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cell 1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cell 2" />
</TableRow>
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cell 3" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cell 4" />
</TableRow>
</TableLayout>
1.4、帧布局(FrameLayout)
特点:
- 控件会堆叠在一起,后添加的控件会覆盖在先前添加的控件之上。
- 布局简单,主要用于容纳单一控件或作为其他布局的容器。
- 通常用于实现特定的视觉效果,如层叠视图。
适用场景:
- 当需要在一个区域内堆叠多个视图时,如实现卡片式UI效果。
- 当作为其他复杂布局的容器时,提供一个简单的层叠环境。
实际应用与示例代码:
例如,创建一个帧布局,其中包含两个文本视图,第二个文本视图会覆盖在第一个文本视图之上。
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Background Text"
android:textSize="24sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Foreground Text"
android:textSize="24sp"
android:textColor="#FF0000"
android:layout_gravity="center" />
</FrameLayout>
1.5、相对布局(RelativeLayout)
特点:
- 控件的位置可以根据其他控件或父容器的边缘来确定。
- 提供了灵活的定位方式,可以方便地实现复杂的布局效果。
- 但过度使用可能导致布局性能下降,因为每次布局测量和布局过程都需要进行多次计算。
适用场景:
- 当需要根据其他控件的位置来定位控件时,如一个按钮位于另一个文本的右侧。
- 当布局相对简单,且性能不是主要考虑因素时。
实际应用与示例代码:
例如,创建一个相对布局,其中包含一个文本视图和一个位于其右侧的按钮。
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click the button"
android:layout_alignParentStart="true"
android:layout_centerVertical="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me"
android:layout_toEndOf="@id/textView"
android:layout_centerVertical="true" />
</RelativeLayout>
2、Android 常用控件介绍
2.1、组件介绍
TextView
特点:用于显示文本内容,可以设置文本颜色、大小、样式等属性。
适用场景:展示静态文本信息,如标题、说明文字等。
EditText
特点:允许用户输入和编辑文本,可以配置为单行或多行输入,支持文本格式化和输入类型限制。
适用场景:需要用户输入信息的场景,如搜索框、表单填写等。
Button
特点:可点击的按钮,用于触发某个动作或事件。
适用场景:用户交互的重要元素,如提交表单、跳转页面等。
RadioButton
特点:单选按钮,允许用户在一组选项中选择一个。
适用场景:需要用户从多个选项中选择一个的场景,如性别选择、支付方式选择等。
CheckBox
特点:复选框,允许用户选择多个选项。
适用场景:需要用户选择多个选项的场景,如兴趣爱好选择、服务条款同意等。
ImageView
特点:用于显示图片,支持多种图片格式,可以设置图片的缩放类型、透明度等属性。
适用场景:展示图片信息的场景,如用户头像、产品图片等。
2.2、实际案例:用户注册表单
以下是一个简单的用户注册表单的XML布局示例,包含了上述控件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<ImageView
android:id="@+id/imageViewLogo"
android:layout_width="38dp"
android:layout_height="37dp"
android:src="@drawable/logo" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="用户注册"
android:textSize="30dp"
android:textStyle="bold" />
<EditText
android:id="@+id/editTextUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Username" />
<EditText
android:id="@+id/editTextEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"
android:inputType="textEmailAddress" />
<EditText
android:id="@+id/editTextPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Password"
android:inputType="textPassword" />
<RadioGroup
android:id="@+id/radioGroupGender"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/radioButtonMale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Male" />
<RadioButton
android:id="@+id/radioButtonFemale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Female" />
</RadioGroup>
<CheckBox
android:id="@+id/checkBoxAgree"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我同意条款和条件" />
<Button
android:id="@+id/buttonRegister"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注册" />
</LinearLayout>
效果展示:
3、Activity与Intent
3.1、Activity
3.1.1、Activity介绍
Activity是Android应用中的一个单独的用户界面。每一个Activity都被给予一个窗口,在其中可以放置UI组件。当一个新的Activity启动时,前一个Activity将会暂停,并压入历史堆栈中。用户可以通过回退操作返回到前一个Activity。Activity是Android应用中非常重要的组件,它代表了用户与应用互动的一个屏幕或一个界面。
3.1.2、Activity生命周期
Activity的生命周期是由Android系统进行管理的,它描述了Activity从创建到销毁所经历的一系列状态。这些状态包括:
- 活动状态(Active/Running):Activity处于任务栈的栈顶,用户可以与其进行交互。
- 暂停状态(Paused):Activity失去了焦点但仍然对用户可见,如栈顶的Activity是透明的或并未铺满整个屏幕。此时,Activity可能因内存不足而被系统杀死。
- 停止状态(Stopped):当Activity被其他Activity完全遮挡时,它对用户不可见,但仍然保留其状态和成员信息。此时,如果系统需要内存,这个Activity也可能会被杀死。
- 销毁状态(Destroyed):Activity被系统从任务栈中移除,如果需要再次显示,必须重新创建和启动。
在Activity的生命周期中,系统会调用一系列的方法,如onCreate()
, onStart()
, onResume()
, onPause()
, onStop()
, 和 onDestroy()
,以便开发者在不同阶段进行相应的操作。
3.1.3、Activity启动模式
Android中的Activity有四种启动模式,它们决定了当启动一个新的Activity时,这个Activity与任务栈中已存在的Activity如何交互。这四种模式是:
-
standard(标准模式):每次启动一个新的Activity都会创建该Activity的新实例,无论该Activity是否已经存在于任务栈中。
-
singleTop(栈顶单例模式):如果新的Activity已经位于任务栈的栈顶,则不会创建新的Activity实例,而是通过调用该实例的
onNewIntent()
方法来传递新的Intent。如果新的Activity不在栈顶,则会创建新的实例并压入栈顶。 -
singleTask(栈内单例模式):在这种模式下,系统会检查任务栈中是否已经存在该Activity的实例。如果存在,则将该实例之上的所有Activity出栈,使其成为栈顶,并调用其
onNewIntent()
方法。如果不存在,则创建新的实例。这意味着,在同一任务栈中,这个Activity只有一个实例存在。 -
singleInstance(全局单例模式):这是一种特殊的启动模式。在这种模式下启动的Activity会运行在一个独立的任务栈中,并且这个Activity在整个应用中只有一个实例。无论从哪里启动这个Activity,都会回到这个已经存在的实例,并且这个实例所在的任务栈中不会有其他Activity存在。如果从这个Activity启动其他Activity,那么新的Activity会运行在新的任务栈中。
3.2、Intent与IntentFilter
3.2.1、Intent:
Intent是一个消息传递对象,可用于请求一个动作。Intent可以用来启动Activity、Service或发送广播。Intent描述了一种操作,可以是启动一个新的Activity,或者是请求一个已经存在的Activity执行某个操作。
- Intent的表现形式(代码):
Intent intent = new Intent(CurrentActivity.this, TargetActivity.class);
startActivity(intent);
- Intent的种类:
- 显式Intent:明确指定了要启动的组件(如Activity的类名)。
- 隐式Intent:不指定具体要启动的组件,而是通过Intent Filter中的action、category、data来匹配能够处理该Intent的组件。
- Intent属性:
setAction()
:设置动作类型。setData()
:设置要操作的数据URI。setType()
:设置数据类型(MIME类型)。setCategory()
:设置Intent的类别。putExtra()
:添加附加数据。
- IntentFilter:
IntentFilter用于描述一个组件(如Activity、Service、BroadcastReceiver)能够响应的Intent类型。它根据Intent的action、data、category来过滤Intent。
3.3、不同页面数据传递(示例代码)
传递数据:
Intent intent = new Intent(CurrentActivity.this, TargetActivity.class);
intent.putExtra("key", "value"); // 传递字符串数据
startActivity(intent);
接收数据(在TargetActivity中):
String value = getIntent().getStringExtra("key"); // 通过key获取传递的数据
3.4、Fragment
Fragment表示Activity中的一个片段或行为。它可以让用户在一个Activity中切换不同的视图或屏幕。Fragment有自己的生命周期,且它的生命周期受宿主Activity的生命周期影响。
使用要点:
- Fragment必须嵌入到Activity中使用。
- Fragment的生命周期与Activity紧密相关。
- 可以通过FragmentManager来管理Fragment(如添加、替换、删除)。
- Fragment之间可以通过接口进行通信。
3.4.1、在Activity中添加Fragment的案例
通过布局文件添加Fragment
在Activity的布局文件中,可以直接使用<fragment>
标签来添加Fragment:
<fragment android:name="com.example.MyFragment"
android:id="@+id/my_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
在Activity中动态添加Fragment
在Activity的代码中,可以使用FragmentManager来动态添加Fragment:
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
MyFragment fragment = new MyFragment();
transaction.add(R.id.fragment_container, fragment); // R.id.fragment_container是容纳Fragment的ViewGroup的ID
transaction.commit();
在这个例子中,MyFragment
是自定义的Fragment类,R.id.fragment_container
是Activity布局中用于容纳Fragment的ViewGroup(如FrameLayout)的ID。通过FragmentTransaction
的add
方法将Fragment添加到容器中,并通过commit
方法提交事务。
4、Android高级控件
4.1、高级控件高级在何处
- 数据适配器的使用:高级控件通常需要与数据适配器(Adapter)配合使用。适配器的作用是将复杂的数据填充到指定的视图界面上。例如,ListView、Spinner、GridView等控件都需要使用适配器来管理和展示数据。这种数据与视图之间的分离设计,使得控件更加灵活和可重用。
- 视图管理与数据绑定的分离:高级控件通常不直接处理数据的展示,而是通过适配器来实现数据与视图的绑定。这种设计模式降低了控件与数据之间的耦合度,提高了代码的可维护性和可扩展性。
- 支持复杂的数据展示:与低级控件相比,高级控件能够展示更复杂的数据结构。例如,通过SimpleAdapter,可以绑定格式复杂的数据,包括文本、图片等多种数据类型。
- 提供丰富的交互功能:高级控件往往支持更丰富的用户交互,如列表项的点击事件监听、滑动切换视图等。这些交互功能提升了用户体验,使得应用更加生动和易用。
- 优化的性能表现:一些高级控件,如RecyclerView,通过引入ViewHolder机制等优化手段,提高了列表滚动的性能表现,减少了不必要的视图创建和销毁操作。
4.2、常用的高级控件
4.2.1、AutoCompleteTextView
AutoCompleteTextView 可以在用户输入时提供自动完成的建议列表
1、添加 AutoCompleteTextView 到布局
<AutoCompleteTextView
android:id="@+id/autoText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionHint="请选择选项"
android:completionThreshold="1"
android:hint="请输入文本" />
2、将 AutoCompleteTextView 与 ArrayAdapter 绑定
AutoCompleteTextView autoText = findViewById(R.id.autoText);
String[] courses = {
"Android入门",
"Android项目实战",
"Android网络开发",
};
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, courses);
autoText.setAdapter(adapter);
效果展示:
4.2.2、Spinner
Spinner 提供下拉选择功能,显示数据集合
1、添加 Spinner 到布局
<Spinner
android:id="@+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
2、创建一个 ArrayAdapter
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.android_development_terms, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
在上述代码中,R.array.
android_development_terms 是一个字符串数组资源,可以在 res/values/arrays.xml
中定义它,例如:
<resources>
<string-array name="android_development_terms">
<item>Activity</item>
<item>Fragment</item>
<item>Intent</item>
<item>Adapter</item>
<item>BroadcastReceiver</item>
<item>Service</item>
<item>ContentProvider</item>
<item>AsyncTask</item>
</string-array>
</resources>
3、将 Spinner 与 ArrayAdapter 绑定
Spinner spinner = (Spinner) findViewById(R.id.spinner);
spinner.setAdapter(adapter);
4、设置 Spinner 的监听器
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selected = parent.getItemAtPosition(position).toString();
Log.i("MyTag", "Selected: " + selected);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// Do something here if needed
}
});
效果展示:
4.2.3、ScrollView、HoriontalScrollView
ScrollView
是一个可以垂直滚动的视图组
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- 放置你的其他视图组件,如TextView, ImageView等 -->
</LinearLayout>
</ScrollView>
HorizontalScrollView
的使用与 ScrollView
类似,但它是水平滚动的。
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<!-- 放置你的其他视图组件,这些组件将会水平排列 -->
</LinearLayout>
</HorizontalScrollView>
4.2.4、ListView
ListView 展示列表数据,支持滚动与交互
1、添加 ListView 到布局
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
2、设置适配器和处理点击事件
// 数据源,一个简单的字符串数组
String[] data = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5"};
// 获取ListView控件的引用
ListView listView = findViewById(R.id.list_view);
// 创建一个ArrayAdapter,将数据源与ListView进行绑定
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, data);
// 设置ListView的适配器
listView.setAdapter(adapter);
// 设置ListView的项点击监听器
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, android.view.View view, int position, long id) {
// 当某个项被点击时,显示一个Toast消息
Toast.makeText(MainActivity.this, "You clicked: " + parent.getItemAtPosition(position), Toast.LENGTH_SHORT).show();
}
});
效果展示:
4.2.5、GridView
GridView
用于以网格形式展示一系列项目
1、布局文件中添加 GridView
<GridView
android:id="@+id/gridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:columnWidth="90dp"
android:stretchMode="columnWidth"
android:gravity="center"/>
2、创建一个适配器来填充 GridView
public class ImageAdapter extends BaseAdapter {
private Context context;
private final Integer[] imageIds = {
R.drawable.logo,
R.drawable.dm1,
R.drawable.dm2,
R.drawable.dm3,
R.drawable.dm4,
R.drawable.cat,
// ... 更多图片资源ID
};
public ImageAdapter(Context c) {
context = c;
}
@Override
public int getCount() {
return imageIds.length;
}
@Override
public Object getItem(int position) {
return imageIds[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(context);
imageView.setLayoutParams(new GridView.LayoutParams(180, 180));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(3, 3, 3, 3);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(imageIds[position]);
return imageView;
}
}
3、在Activity
中设置 GridView
的适配器,并为其添加点击事件监听器
GridView gridView = findViewById(R.id.gridView);
gridView.setAdapter(new ImageAdapter(this));
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this, "You clicked item " + position,Toast.LENGTH_SHORT).show();
}
});
效果展示:
4.2.6、ProgressBar、SeekBar
4.2.6.1、ProgressBar
ProgressBar
可以用来显示一个任务的进度。以下是如何在布局文件中添加一个 ProgressBar
和如何在代码中更新它的进度的示例:
1、XML 布局文件
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0" />
2、Java 代码 (MainActivity.java):
ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progressBar);
// 模拟进度更新
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
final int progress = i;
runOnUiThread(new Runnable() {
@Override
public void run() {
progressBar.setProgress(progress);
}
});
try {
Thread.sleep(100); // 模拟耗时任务
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
效果展示:
4.2.6.2、SeekBar
SeekBar
允许用户通过滑动条来选择一个值。以下是如何在布局文件中添加一个 SeekBar
和如何在代码中处理其值变化的示例:
1、XML 布局文件
<TextView
android:id="@+id/progressText"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<SeekBar
android:id="@+id/seekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100" />
2、Java 代码 (MainActivity.java
):
SeekBar seekBar;
TextView progressText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
seekBar = findViewById(R.id.seekBar);
progressText = findViewById(R.id.progressText); // 用TextView 来显示进度值
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
progressText.setText("Progress: " + progress); // 更新 TextView 以显示当前进度值
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) { } // 可以根据需要实现这些方法
@Override
public void onStopTrackingTouch(SeekBar seekBar) { } // 可以根据需要实现这些方法
});
}
效果展示:
4.2.7、选项卡(TabHost、TabWidget、FrameLayout)
在Android中,TabHost
, TabWidget
, 和 FrameLayout
常被一起使用来创建一个带有选项卡的用户界面。以下是一个简单的示例代码,展示了如何使用这些组件:
1、XML 布局文件
<TabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<!-- 在这里添加你的选项卡内容 -->
<!-- 例如,两个TextView作为两个选项卡的内容 -->
<TextView
android:id="@+id/textview1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="这是选项卡1的内容" />
<TextView
android:id="@+id/textview2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="这是选项卡2的内容"
android:visibility="gone"/> <!-- 初始时设置为不可见 -->
</FrameLayout>
</LinearLayout>
</TabHost>
2、Java 代码 (MainActivity.java
):
TabHost tabHost = findViewById(android.R.id.tabhost);
TabWidget tabWidget = findViewById(android.R.id.tabs);
FrameLayout tabContent = findViewById(android.R.id.tabcontent);
// 设置选项卡内容
tabHost.setup();
// 创建选项卡1
TabHost.TabSpec tabSpec1 = tabHost.newTabSpec("Tab 1");
tabSpec1.setContent(R.id.textview1);
tabSpec1.setIndicator("选项卡1");
tabHost.addTab(tabSpec1);
// 创建选项卡2
TabHost.TabSpec tabSpec2 = tabHost.newTabSpec("Tab 2");
tabSpec2.setIndicator("选项卡2");
tabHost.addTab(tabSpec2);
// 设置选项卡更改监听器(可选)
tabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
public void onTabChanged(String tabId) {
if ("Tab 1".equals(tabId)) {
findViewById(R.id.textview1).setVisibility(View.VISIBLE);
findViewById(R.id.textview2).setVisibility(View.GONE);
} else if ("Tab 2".equals(tabId)) {
findViewById(R.id.textview1).setVisibility(View.GONE);
findViewById(R.id.textview2).setVisibility(View.VISIBLE);
}
}
});
效果展示:
4.2.8、ViewPager2
ViewPager2
是 Android Jetpack 组件库中的一个控件,用于在屏幕上水平或垂直滑动视图。
1、添加依赖
首先,在 build.gradle
文件中添加 ViewPager2
的依赖
dependencies {
implementation 'androidx.viewpager2:viewpager2:1.0.0'
}
2、创建布局文件
在布局文件中添加 ViewPager2
控件
<!-- res/layout/activity_main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
3、创建适配器
创建一个继承自 RecyclerView.Adapter
的适配器类,用于提供 ViewPager2
显示的数据
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class ViewPagerAdapter extends RecyclerView.Adapter<ViewPagerAdapter.ViewHolder> {
private int[] imageResources;
public ViewPagerAdapter(int[] imageResources) {
this.imageResources = imageResources;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.pager_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.imageView.setImageResource(imageResources[position]);
}
@Override
public int getItemCount() {
return imageResources.length;
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public ViewHolder(@NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageView);
}
}
}
其中,pager_item
是每个页面项的布局,如下所示
<!-- res/layout/pager_item.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop" />
</LinearLayout>
4、在 Activity 中设置 ViewPager2
在 Activity
中初始化 ViewPager2
并设置适配器
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private ViewPager2 viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = findViewById(R.id.viewPager);
int[] imageResources = new int[]{R.drawable.image1, R.drawable.image2, R.drawable.image3}; // 替换为你的图片资源ID
ViewPagerAdapter adapter = new ViewPagerAdapter(imageResources);
viewPager.setAdapter(adapter);
}
}
5、Android菜单与对话框设计
5.1、菜单
5.1.1、OptionsMenu(选项菜单)
在Android中,OptionsMenu通常位于屏幕的右上角,以三个垂直点的图标显示。用户点击该图标时,会显示一个下拉菜单。
代码示例:
1、在res/menu
目录下创建一个XML文件来定义菜单项
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
app:showAsAction="never" />
</menu>
2、在Activity中重写onCreateOptionsMenu()
和onOptionsItemSelected()
方法
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
// 处理设置菜单项的点击事件
return true;
}
return super.onOptionsItemSelected(item);
}
5.1.2、ContextMenu(上下文菜单)
ContextMenu(上下文菜单)通常用于在用户长按某个视图时显示一个菜单,提供与该视图相关的操作选项。
代码示例:
1、XML:
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="长按我显示上下文菜单"
android:textSize="20dp"
/>
2、Java 代码 (MainActivity.java
):
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注册上下文菜单
registerForContextMenu(findViewById(R.id.textView));
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
// 添加菜单项
menu.add(0, 1, 0, "选项1");
menu.add(0, 2, 0, "选项2");
menu.add(0, 3, 0, "选项3");
}
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 1:
// 处理选项1的点击事件
Toast.makeText(this, "你点击了选项1", Toast.LENGTH_SHORT).show();
return true;
case 2:
// 处理选项2的点击事件
Toast.makeText(this, "你点击了选项2", Toast.LENGTH_SHORT).show();
return true;
case 3:
// 处理选项3的点击事件
Toast.makeText(this, "你点击了选项3", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onContextItemSelected(item);
}
}
}
效果展示:
5.2、对话框
5.2.1、AlertDialog(普通对话框)
AlertDialog
是一个用于显示对话框的便捷类,它可以显示一个标题、一些文本、最多三个按钮以及一个可选的列表视图。
代码示例:
1、XML:
<Button
android:id="@+id/show_dialog_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="button"/>
2、Java 代码 (MainActivity.java
):
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 绑定布局文件中的按钮,点击后会弹出AlertDialog
Button showDialogButton = findViewById(R.id.show_dialog_button);
showDialogButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showAlertDialog();
}
});
}
private void showAlertDialog() {
// 创建AlertDialog.Builder对象
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// 设置对话框的标题和消息
builder.setTitle("标题");
builder.setMessage("这是一个AlertDialog示例。");
// 添加“确定”按钮及其点击事件
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 确定按钮的点击事件
// 在这里编写确定后的操作
}
});
// 添加“取消”按钮及其点击事件
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 取消按钮的点击事件
// 在这里编写取消后的操作,或者什么都不做直接关闭对话框
}
});
// 创建并显示AlertDialog
AlertDialog dialog = builder.create();
dialog.show();
}
}
效果展示:
5.2.2、AlertDialog.Builder(灵活对话框)
AlertDialog.Builder
是 Android 中用于构建 AlertDialog
的一个便捷的类。它提供了一种链式调用的方式来配置和显示对话框。
示例代码:
1、XML:
<Button
android:id="@+id/show_dialog_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="button"/>
2、Java 代码 (MainActivity.java
):
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 假设你的布局文件中有一个按钮,点击后会弹出AlertDialog
Button showDialogButton = findViewById(R.id.show_dialog_button);
showDialogButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showFlexibleAlertDialog();
}
});
}
private void showFlexibleAlertDialog() {
// 创建AlertDialog.Builder对象
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// 设置对话框的标题
builder.setTitle("请选择一个选项");
// 设置单选列表及其点击事件
String[] items = {"选项1", "选项2", "选项3"};
builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// which 是被点击的项目的索引
Toast.makeText(MainActivity.this, "你选择了: " + items[which], Toast.LENGTH_SHORT).show();
dialog.dismiss(); // 关闭对话框
}
});
// 设置取消按钮及其点击事件(可选)
builder.setNegativeButton("取消", null); // 如果不需要执行任何操作,可以传入null
// 创建并显示AlertDialog
AlertDialog dialog = builder.create();
dialog.show();
}
}
效果展示:
结束语:
通过本次总结,回顾了《APP应用开发》课程中关于Android布局与控件、Activity与Intent以及高级控件与交互设计等方面的知识。这些知识为我构建功能丰富、界面美观的Android应用提供了坚实的基础。在未来的学习和实践中,我将继续深入探索Android开发的奥秘,不断提升自己的技能水平。
参考文献: