Fragment,所有Android问题的解决方案

前言

目前,Android已经可以运行在各种各样的设备中,有小屏幕的手机,超大屏的平板甚至电视。由于屏幕尺寸的差距,很多情况下,都是先针对手机开发一App,然后拷贝一份,修改布局以适应平板神马超级大屏的。难道无法做到一个App可以同时适应手机和平板么?Fragment的出现就是为了解决这样的问题。可以认为Fragment当成Activity的一个界面的一个组成部分,甚至Activity的界面可以完全有不同的Fragment组成,且Fragment还拥有自己的生命周期和接收、处理用户的事件,这样就可以动态的添加、替换和移除某个Fragment。

目录
* Fragment的生命周期图及其要点学习
* Fragment的创建
* Fragment与Activity的交互
* Fragment与Activity的demo实现

谷歌安卓开发者文档:A Fragment is a piece of an application's user interface or behavior that can be placed in an Activity. Interaction with fragments is done through FragmentManager, which can be obtained via Activity.getFragmentManager() and Fragment.getFragmentManager().
The Fragment class can be used many ways to achieve a wide variety of results. In its core, it represents a particular operation or interface that is running within a larger Activity. A Fragment is closely tied to the Activity it is in, and can not be used apart from one. Though Fragment defines its own lifecycle, that lifecycle is dependent on its activity: if the activity is stopped, no fragments inside of it can be started; when the activity is destroyed, all fragments will be destroyed.
All subclasses of Fragment must include a public no-argument constructor. The framework will often re-instantiate a fragment class when needed, in particular during state restore, and needs to be able to find this constructor to instantiate it. If the no-argument constructor is not available, a runtime exception will occur in some cases during state restore.

1,Fragment的生命周期

Fragment,所有Android问题的解决方案_第1张图片
image.png

使用Fragment的一些要点:
3.0版本后引入,即minSdk要大于11
Fragment需要嵌套在Activity中使用,当然也可以嵌套到另外一个Fragment中,但这个被嵌套 的Fragment也是需要嵌套在Activity中的,间接地说,Fragment还是需要嵌套在Activity中!! 受寄主Activity的生命周期影响,当然他也有自己的生命周期!另外不建议在Fragment里面 嵌套Fragment因为嵌套在里面的Fragment生命周期不可控!!!
官方文档说创建Fragment时至少需要实现三个方法:onCreate( ),onCreateView( ),OnPause( ); 不过貌似只写一个onCreateView也是可以的...
Fragment的生命周期和Activity有点类似:三种状态:
Resumed:在允许中的Fragment可见
Paused:所在Activity可见,但是得不到焦点
Stoped: ①调用addToBackStack(),Fragment被添加到Bcak栈 ②该Activity转向后台,或者该Fragment被替换/删除
ps:停止状态的fragment仍然活着(所有状态和成员信息被系统保持着),然而,它对用户 不再可见,并且如果activity被干掉,他也会被干掉.
Fragment的几个子类:

ps:很多时候我们都是直接重写Fragment,inflate加载布局完成相应业务了,子类用的不多,等需要的 时候在深入研究!
对话框:DialogFragment
列表:ListFragment
选项设置:PreferenceFragment
WebView界面:WebViewFragment

  • Fragment的布局

Fragments can be used as part of your application's layout, allowing you to better modularize your code and more easily adjust your user interface to the screen it is running on. As an example, we can look at a simple program consisting of a list of items, and display of the details of each item.
An activity's layout XML can include tags to embed fragment instances inside of the layout. For example, here is a simple layout that embeds one fragment:
android:layout_width="match_parent" android:layout_height="match_parent">
android:id="@+id/titles"
android:layout_width="match_parent" android:layout_height="match_parent" />

The layout is installed in the activity in the normal way:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.fragment_layout);

}

  • v4的fragment与Android的fragment

其实都可以,前面说过Fragment是Android 3.0(API 11)后引入的,那么如果开发的app需要 在3.0以下的版本运行呢?比如还有一点点市场份额的2.3!于是乎,v4包就这样应运而生了, 而最低可以兼容到1.6版本!至于使用哪个包看你的需求了,现在3.0下手机市场份额其实已经不多了,随街都是4.0以上的,6.0十月份都出了,你说呢...所以这个时候,你可以直接使用app包下的Fragment 然后调用相关的方法,通常都是不会有什么问题的;如果你Fragment用了app包的, FragmentManager和FragmentTransaction都需要是app包的!要么用全部用app,要么全部用v4, 不然可是会报错的哦!当然如果你要自己的app对于低版本的手机也兼容的话,那么就可以选择用v4包!
使用v4包下Fragment要注意的地方:
①如果你使用了v4包下的Fragment,那么所在的那个Activity就要继承FragmentActivity哦! 案例:今天在xml文件中静态地载入fragment,然后重写了Fragment,但是在加载Activity的时候就报错了, 大概的提示就是Fragment错误还是找不到什么的,name属性改了几次还是错!最后才发现是用了 v4的包的缘故,只需让自己的Activity改成FragmentActivity即可!
②之前写了下面这段代码,然后报错: 有点莫名其妙啊,Fragment,FragmentManager,FragmentTransaction都是用的v4包啊, Activity也是继承FragmentActivity的啊?都改成app包就可以了,但是这不和我们用v4包的 前提冲突了么?其实也是有解决方法的哈?
答:只需要把getFragmentManager( )改成getSupportFragmentManager( )就可以了

2,Fragment的创建

  •     静态加载
    
Fragment,所有Android问题的解决方案_第2张图片
image.png

示例代码:
Step 1:定义Fragment的布局,就是fragment显示内容的
Step 2:自定义一个Fragment类,需要继承Fragment或者他的子类,重写onCreateView()方法 在该方法中调用:inflater.inflate()方法加载Fragment的布局文件,接着返回加载的view对象
public class Fragmentone extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment1, container,false);
return view;
}
}
Step 3:在需要加载Fragment的Activity对应的布局文件中添加fragment的标签, 记住,name属性是全限定类名哦,就是要包含Fragment的包名,如:
android:id="@+id/fragment1"
android:name="com.jay.example.fragmentdemo.Fragmentone"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
Step 4: Activity在onCreate( )方法中调用setContentView()加载布局文件即可!

  • 动态加载
Fragment,所有Android问题的解决方案_第3张图片
image.png

3,Fragment与Activity的交互

Fragment,所有Android问题的解决方案_第4张图片
image.png

1)组件获取

Fragment获得Activity中的组件: getActivity().findViewById(R.id.list);
Activity获得Fragment中的组件(根据id和tag都可以):getFragmentManager.findFragmentByid(R.id.fragment1);
2)数据传递

①Activit传递数据给Fragment:
在Activity中创建Bundle数据包,调用Fragment实例的setArguments(bundle) 从而将Bundle数据包传给Fragment,然后Fragment中调用getArguments获得 Bundle对象,然后进行解析就可以了
②Fragment传递数据给Activity
在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口, Fragment就可以通过回调接口传数据了,回调,相信很多人都知道是什么玩意,但是 写不出来啊,网上的一百度"fragment传数据给Activity",全是李刚老师的那个代码,真心无语 算了,这里就写下局部代码吧,相信读者一看就懂的了:
Step 1:定义一个回调接口:(Fragment中)
/接口/
public interface CallBack{
/定义一个获取信息的方法/
public void getResult(String result);
}
Step 2:接口回调(Fragment中)
/接口回调/
public void getData(CallBack callBack){
/获取文本框的信息,当然你也可以传其他类型的参数,看需求咯/
String msg = editText.getText().toString();
callBack.getResult(msg);
}
Step 3:使用接口回调方法读数据(Activity中)
/* 使用接口回调的方法获取数据 /
leftFragment.getData(new CallBack() {
@Override
public void getResult(String result) { /
打印信息*/
Toast.makeText(MainActivity.this, "-->>" + result, 1).show();
}
});
总结下方法: ->在Fragment定义一个接口,接口中定义抽象方法,你要传什么类型的数据参数就设置为什么类型;
->接着还有写一个调用接口中的抽象方法,把要传递的数据传过去
->再接着就是Activity了,调用Fragment提供的那个方法,然后重写抽象方法的时候进行数据 的读取就可以
Fragment与Fragment之间的数据互传
其实这很简单,找到要接受数据的fragment对象,直接调用setArguments传数据进去就可以了 通常的话是replace时,即fragment跳转的时候传数据的,那么只需要在初始化要跳转的Fragment 后调用他的setArguments方法传入数据即可!
如果是两个Fragment需要即时传数据,而非跳转的话,就需要先在Activity获得f1传过来的数据, 再传到f2了,就是以Activity为媒介~
示例代码如下:
FragmentManager fManager = getSupportFragmentManager( );
FragmentTransaction fTransaction = fManager.beginTransaction();
Fragmentthree t1 = new Fragmentthree();
Fragmenttwo t2 = new Fragmenttwo();
Bundle bundle = new Bundle();
bundle.putString("key",id);
t2.setArguments(bundle);
fTransaction.add(R.id.fragmentRoot, t2, "~~~");
fTransaction.addToBackStack(t1);
fTransaction.commit();

4,Fragment与Activity的demo实现

  • 布局代码
    1.actvity_main.xml


xmlns:app="http://schemas.android.com/apk/res-auto";
xmlns:tools="http://schemas.android.com/tools";
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.luolu.fragmentbottomdemo.MainActivity">



    


    







    

    

    

    









2.fg_content.xml


xmlns:android="http://schemas.android.com/apk/res/android";
android:layout_width="match_parent"
android:layout_height="match_parent">


Resource
1.ic_launcher_background.xml


android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z" />
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />

ic_launcher_foreground.xml


android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z" />
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />

  • MainActivity.java

package com.example.luolu.fragmentbottomdemo;

import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

//UI Object
private TextView txt_topbar;
private TextView txt_channel;
private TextView txt_message;
private TextView txt_better;
private TextView txt_setting;
private FrameLayout ly_content;

//Fragment Object
private MyFragment fg1,fg2,fg3,fg4;
private FragmentManager fManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_main);
    fManager = getFragmentManager();
    bindViews();
    txt_channel.performClick();   //模拟一次点击,既进去后选择第一项
}

//UI组件初始化与事件绑定
private void bindViews() {
    txt_topbar = (TextView) findViewById(R.id.txt_topbar);
    txt_channel = (TextView) findViewById(R.id.txt_channel);
    txt_message = (TextView) findViewById(R.id.txt_message);
    txt_better = (TextView) findViewById(R.id.txt_better);
    txt_setting = (TextView) findViewById(R.id.txt_setting);
    ly_content = (FrameLayout) findViewById(R.id.ly_content);

    txt_channel.setOnClickListener(this);
    txt_message.setOnClickListener(this);
    txt_better.setOnClickListener(this);
    txt_setting.setOnClickListener(this);
}

//重置所有文本的选中状态
private void setSelected(){
    txt_channel.setSelected(false);
    txt_message.setSelected(false);
    txt_better.setSelected(false);
    txt_setting.setSelected(false);
}

//隐藏所有Fragment
private void hideAllFragment(FragmentTransaction fragmentTransaction){
    if(fg1 != null) {
        fragmentTransaction.hide(fg1);
    }
    if(fg2 != null) {
        fragmentTransaction.hide(fg2);
    }
    if(fg3 != null) {
        fragmentTransaction.hide(fg3);
    }
    if(fg4 != null) {
        fragmentTransaction.hide(fg4);
    }
}


@Override
public void onClick(View v) {
    FragmentTransaction fTransaction = fManager.beginTransaction();
    hideAllFragment(fTransaction);
    switch (v.getId()){
        case R.id.txt_channel:
            setSelected();
            txt_channel.setSelected(true);
            if(fg1 == null){
                fg1 = new MyFragment("我是第一个Fragment");
                fTransaction.add(R.id.ly_content,fg1);
            }else{
                fTransaction.show(fg1);
            }
            break;
        case R.id.txt_message:
            setSelected();
            txt_message.setSelected(true);
            if(fg2 == null){
                fg2 = new MyFragment("我是第二个Fragment");
                fTransaction.add(R.id.ly_content,fg2);
            }else{
                fTransaction.show(fg2);
            }
            break;
        case R.id.txt_better:
            setSelected();
            txt_better.setSelected(true);
            if(fg3 == null){
                fg3 = new MyFragment("我是第三个Fragment");
                fTransaction.add(R.id.ly_content,fg3);
            }else{
                fTransaction.show(fg3);
            }
            break;
        case R.id.txt_setting:
            setSelected();
            txt_setting.setSelected(true);
            if(fg4 == null){
                fg4 = new MyFragment("我是第四个Fragment");
                fTransaction.add(R.id.ly_content,fg4);
            }else{
                fTransaction.show(fg4);
            }
            break;
    }
    fTransaction.commit();
}

}

  • MyFragment.java

package com.example.luolu.fragmentbottomdemo;

import android.annotation.SuppressLint;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**

  • @author luolu
  • @date 2017/11/17
    */

@SuppressLint("ValidFragment")
public class MyFragment extends Fragment {

private String content;
public MyFragment(String content) {
    this.content = content;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fg_content,container,false);
    TextView txt_content = (TextView) view.findViewById(R.id.txt_content);
    txt_content.setText(content);
    return view;
}

}

资源文件没全部复制过来,这里截个图


Fragment,所有Android问题的解决方案_第5张图片
image.png

运行结果截图:


Fragment,所有Android问题的解决方案_第6张图片
image.png

demo中的底部的图片,大家自己换一下!!

你可能感兴趣的:(Fragment,所有Android问题的解决方案)