一、让片段与活动交互
修改片段显示一个项目的详细信息而不是目前的占位文本。更新fragment_workout_detail.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/textTitle" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textDescription" />
LinearLayout>
相比之前的,删掉了两个android:text。
二、Workout类
我们将训练项目数据保存在一个名为Workout.java的文件,这是一个纯java类,应用将从这个文件获得训练项目数据。这个类定义了一个包含4个训练项目的数组,每个训练项目包括一个名字和一个描述。
在com.hfad.workout中新建一个java类即可。
public class Workout {
private String name;
private String description;
public static final Workout[] workouts = {
new Workout("The Limb Loosener",
"5 Handstand push-ups\n10 1-legged squats\n15 Pull-ups"),
new Workout("Core Agony",
"100 Pull-ups\n100 Push-ups\n100 Sit-ups\n100 Squats"),
new Workout("The Wimp Special",
"5 Pull-ups\n10 Push-ups\n15 Squats"),
new Workout("Strength and Length",
"500 meter run\n21 x 1.5 pood kettleball swing\n21 x pull-ups")
};
//Each Workout has a name and description
private Workout(String name, String description) {
this.name = name;
this.description = description;
}
public String getDescription() {
return description;
}
public String getName() {
return name;
}
public String toString() {
return this.name;
}
}
三、向片段传递训练项目ID
通过ID来标识唯一的一个项目,所以修改WorkoutDetailFragment如下:
package com.hfad.workout;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class WorkoutDetailFragment extends Fragment {
//用来表示用户选择的训练项目的ID
private long workoutId;
@Override
//Android需要这个片段的布局时会调用这个方法
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// 这会告诉Android这个片段使用哪个布局
return inflater.inflate(R.layout.fragment_workout_detail, container, false);
}
public void setWorkoutId(long id) {
this.workoutId = id;
}
}
四、使用片段管理器管理片段
在活动与片段交互之前,活动首先需要得到这个片段的一个引用。可以使用活动的片段管理器来得到活动片段的引用。片段管理器用于跟踪和处理活动使用的所有片段。
要得到片段管理器的一个引用,可以使用getFragmentManager()和getSupportFragmentManager()。后者会得到处理支持库片段的片段管理器的一个引用,前者得到处理其他片段的片段管理器的引用,这些片段使用原生的Android片段类。然后可以使用片段管理器的fingFragmentById方法得到片段的一个引用。
其使用方法如下:
getSupportFragmentManager().findFragmentById()
首先、在activity_detail.xml中为片段增加一个ID。
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.hfad.workout.WorkoutDetailFragment"
android:id="@+id/detail_frag"
android:layout_width="match_parent"
android:layout_height="match_parent">
fragment>
然后在DetailActivity.java中设置训练项目ID。
package com.hfad.workout;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class DetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
WorkoutDetailFragment frag = (WorkoutDetailFragment)getSupportFragmentManager().findFragmentById(R.id.detail_frag);
frag.setWorkoutId(1);
};
}
五、片段生命周期
片段的生命周期和活动的生命周期很类似,不过片段生命周期中还有另外几个步骤。这是因为他需要包含这个片段的活动的生命周期交互。
在安卓开发中,片段(Fragment)的生命周期主要包含以下几种方法:
onAttach():片段被附加到活动时调用。
onCreate():在创建片段时调用,可以在这里进行初始化的操作。
onCreateView():用于创建并返回该片段的视图。
onActivityCreated():在活动创建片段之后调用。
onStart():当片段可见时调用。
onResume():当片段恢复到前台并可以与用户交互时调用。
onPause():当片段暂停并且用户交互停止时调用。
onStop():当片段不可见时调用。
onDestroyView():在销毁片段之前调用,可以在这里释放视图资源。
onDestroy():在销毁片段时调用,可以在这里进行清理操作。
onDetach():片段从活动中分离时调用。
另外的,Fragment类是继承自java.lang.Object类的,并不扩展Activity类,这表明活动可用的一些方法在片段中无法使用。
需要说明的是:Fragment没有实现context类。与活动不同,片段并不是一个上下文类型,不能直接访问有关应用环境的全局信息。实际上,片段必须使用其他对象的上下文来访问这个信息,如它的父活动。
六、在onStart方法中设置视图的值
要在活动可见时完成片段视图的更新,所以要使用片段的onStart方法。更新WorkoutDetailFragment代码如下:
package com.hfad.workout;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class WorkoutDetailFragment extends Fragment {
//用来表示用户选择的训练项目的ID
private long workoutId;
@Override
//Android需要这个片段的布局时会调用这个方法
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// 这会告诉Android这个片段使用哪个布局
return inflater.inflate(R.layout.fragment_workout_detail, container, false);
}
public void onStart() {
super.onStart();
//得到片段的根视图,然后使用这个根视图得到两个文本视图的引用
View view = getView();
if (view != null) {
TextView title = (TextView) view.findViewById(R.id.textTitle);
Workout workout = Workout.workouts[(int)workoutId];
title.setText(workout.getName());
TextView description = (TextView) view.findViewById(R.id.textDescription);
description.setText(workout.getDescription());
}
}
public void setWorkoutId(long id) {
this.workoutId = id;
}
}
由于片段于活动不同,因此片段没有包含活动的所有方法,片段没有findViewById方法,要得到片段中视图的引用,首先必须使用geyView方法得到片段根视图的引用,然后使用根视图查找它的子视图。
现在可以运行一下应用。