片段与活动的交互

一、让片段与活动交互
修改片段显示一个项目的详细信息而不是目前的占位文本。更新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方法得到片段根视图的引用,然后使用根视图查找它的子视图。
现在可以运行一下应用。

你可能感兴趣的:(Android实践,android)