安卓Fragment快速入门

版权声明:本文为 宇不语 原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35064774/article/details/52622714

如有转载,请申明:

转载至 http://blog.csdn.net/qq_35064774/article/details/52622714


Fragment虽然不是四大组件之一,但在界面布局方面非常重要。

Fragment的作用

FragmentAPI11时新引入的轻量级”Activity”。目的是为了更方便的适配大小屏幕,在平板和手机上可以有完全不同的Fragment。可以很方便的动态添加删除Fragment

Fragment的编写

Fragment类似于Activity,只要继承Fragment类即可。

package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
import com.ittianyu.basictest.R;
 
public class StaticUseFragment extends Fragment {
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
 
        return inflater.inflate(R.layout.fragment_display, container, false);
    }
}

上述代码为最简单的Fragment,只有onCreateView这一个生命周期方法。

这个方法会在创建Fragment视图时调用,需要返回要显示的View

这里返回的是fragment_display.xml的视图。下面附上代码

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#440000ff"
    tools:context="com.ittianyu.basictest.fragmentquickstart.DisplayFragment">
 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="display fragment" />
 
</FrameLayout>

Fragment的静态引用

自己编写的Fragment可以像其他控件一样,直接在xml中引用。

具体引用代码如下。


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.ittianyu.basictest.fragmentquickstart.FragmentQuickStartActivity">
 
    <fragment
        android:id="@+id/f_static_use"
        android:name="com.ittianyu.basictest.fragmentquickstart.StaticUseFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
 
</LinearLayout>


只需要使用fragment标签,然后加上name属性,指定要引用的Fragment对象即可。

但值得注意的时,这样做的时候,我的Android Studio IDE报了一个警告,不推荐这么做。

Fragment的动态引用

先分别编写3Fragment

package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
 
import com.ittianyu.basictest.R;
 
public class SoundFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_sound, container, false);
        return view;
    }
}
 
 
 
package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
import com.ittianyu.basictest.R;
 
 
public class SaveFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_save, container, false);
    }
}
 
 
package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
import com.ittianyu.basictest.R;
 
public class DisplayFragment extends Fragment {
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_display, container, false);
    }
}

这三个Fragment和最开始介绍的编写方式差不多,只是换了个xml界面。

接下来是三个xml的代码

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#44ff0000"
    tools:context="com.ittianyu.basictest.fragmentquickstart.SoundFragment">
 
    <Button
        android:id="@+id/btn_get_text"
        android:text="获取activity中的文本内容"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
 
</FrameLayout>
 
 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#4400ff00"
    tools:context="com.ittianyu.basictest.fragmentquickstart.SaveFragment">
 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="save fragment" />
 
</FrameLayout>
 
 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#440000ff"
    tools:context="com.ittianyu.basictest.fragmentquickstart.DisplayFragment">
 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="display fragment" />
 
</FrameLayout>

有了Fragment,我们接下来写动态引用Fragment的类。

package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
 
import com.ittianyu.basictest.R;
 
public class FragmentQuickStartActivity extends AppCompatActivity implements View.OnClickListener {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment_quick_start);
 
        init();
    }
 
    /**
     * 初始化按钮事件
     */
    private void init() {
        findViewById(R.id.sound).setOnClickListener(this);
        findViewById(R.id.display).setOnClickListener(this);
        findViewById(R.id.save).setOnClickListener(this);
 
        sound();
    }
 
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.sound:
                sound();
                break;
            case R.id.display:
                display();
                break;
            case R.id.save:
                save();
                break;
        }
    }
 
    /**
     * 显示sound fragment
     */
    private void sound() {
        // 获得fragment管理对象(使用v4包向下兼容)
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.frame, new SoundFragment());
        transaction.commit();
    }
    /**
     * 显示sound fragment
     */
    private void save() {
        // 获得fragment管理对象(使用v4包向下兼容)
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.frame, new SaveFragment());
        transaction.commit();
    }
    /**
     * 显示sound fragment
     */
    private void display() {
        // 获得fragment管理对象(使用v4包向下兼容)
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.frame, new DisplayFragment());
        transaction.commit();
    }
}

结构很简单的代码,三个按钮点击之后,分别显示相应的Fragment

对了,还没贴出该Activity对应的xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.ittianyu.basictest.fragmentquickstart.FragmentQuickStartActivity">
 
    <EditText
        android:id="@+id/et_content"
        android:hint="请输入内容"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
 
    <FrameLayout
        android:id="@+id/frame"
        android:layout_weight="3"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>
 
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/sound"
            android:text="声音"
            android:layout_weight="1"
            android:layout_width="0dip"
            android:layout_height="wrap_content" />
        <Button
            android:id="@+id/display"
            android:text="显示"
            android:layout_weight="1"
            android:layout_width="0dip"
            android:layout_height="wrap_content" />
        <Button
            android:id="@+id/save"
            android:text="存储"
            android:layout_weight="1"
            android:layout_width="0dip"
            android:layout_height="wrap_content" />
    </LinearLayout>
 
</LinearLayout>

下面解释一下如何动态引用fragment

首先我们要管理fragment就需要一个FragmentManager

FragmentManager manager = getSupportFragmentManager();

然后通过管理器,开启一个事务,这样是为了一次性提交,防止界面花屏。

FragmentTransaction transaction = manager.beginTransaction();

拿着事务去替换fragment,也就是把Fragment放入到了idframe的控件中。

transaction.replace(R.id.frame, new DisplayFragment());

最后提交修改

transaction.commit();


运行之后,我们应该会看到如下界面。

点击不同的按钮会切换到相应的Fragment

然后你会看到图中Fragment中有个按钮是用来获取Activity中的EditText的中内容的。但是上面代码并没有实现,那么如何实现呢?

请继续往下看。


FragmentActivity交互

Fragment必须依赖Activity才能存在,所以一般来说都会持有Activity的引用,事实上API也是这样设计的。

Fragment类中,可以通过getActivity拿到Fragment所在的Activity引用。

因此,要实现点击Fragment中的按钮获取Activity控件内容,也变得很容易。

package com.ittianyu.basictest.fragmentquickstart;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
 
import com.ittianyu.basictest.R;
 
public class SoundFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_sound, container, false);
        // 设置fragment中的按钮的点击事件
        view.findViewById(R.id.btn_get_text).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 拿到fragment所处的activity,然后获取其中的edittext的内容,显示出来
                EditText etContent = (EditText) getActivity().findViewById(R.id.et_content);
                String content = etContent.getText().toString().trim();
                if(TextUtils.isEmpty(content)) {
                    Toast.makeText(getActivity(), "文本内容为空", Toast.LENGTH_SHORT).show();
                   return;
                }
                Toast.makeText(getActivity(), content, Toast.LENGTH_SHORT).show();
            }
        });
 
        return view;
    }
}

Fragment向下兼容

在文章开头就介绍了FragmentAPI11时才加入安卓的,也就是安卓3.0以后才可以使用Fragment,然而谷歌早就看穿了一切,为我们提供了向下兼容包,也就是常说的support包。

为了在低版本中使用Fragment,我们需要使用的是support.v4中的Fragment,而我们上面的代码也是这样做的,细心的你应该会发现我导入的是

import android.support.v4.app.Fragment;

而不是

import android.app.Fragment;

同样的,在Activity中,导入的也是v4的包

import android.support.v4.app.FragmentManager;

import android.support.v4.app.FragmentTransaction;

使用v4包的Fragment与正常的Fragment几乎没有差别,但有一个地方需要注意。

V4包时,获取FragmentManager要用getSupportFragmentManager,也就是如下。

FragmentManager manager = getSupportFragmentManager();

而如果是非兼容的API,则用的是getFragmentManager()

最后还需要提醒一点的是,现在(2016)安卓4.0以下的设备非常少了,基本都是上5.0。所以,一般情况下也没有必要向下兼容了。

猜你喜欢

转载自blog.csdn.net/qq_35064774/article/details/52622714