fragment的使用以及fragment大家族解析
来源:互联网 发布:女朋友说我不懂她 知乎 编辑:程序博客网 时间:2024/04/30 21:31
fragment作为用户交互的组件之一,大家都经常接触到。对于fragment的操作不熟悉,会导致很多逻辑的错误。尤其是对它的生命周期的模糊不清,很容易导致fragment初始化失败。而通过fragment事务的操作,可以让我们写代码的时候更加模块化,所以很有必要了解FragmentTransaction这个东西。其次,fragment经常作为屏幕适配的一个解决方案,所以在后面的例子会讲解同一个屏幕使用双fragment的情况以及fragment与activity的相互交互的情况。下面逐一介绍FragmentTransaction,Fragmentmanger,Fragment,ListFragment,DialogFragment,WebViewFragment。
一、FragmentTransaction
public abstract FragmentTransaction add(int containerViewId, Fragment fragment, String tag)
public abstract FragmentTransaction replace(int containerViewId, Fragment fragment, String tag);
用于替换已经存在的安置于containerViewId的fragment。注意执行完操作记得使用FragmentManager.commit方法进行事务的提交。此方法等同于通过移除所有与containerViewid的相关的fragment,然后再通过add方法将当前fragment添加进去。
public abstract FragmentTransaction remove(Fragment fragment);
从activity中移除指定的已存在的fragment,如果当前fragment正好添加进了activity的视图容器了,那么fragment的视图也会被移除。
参数解析:
fragment:将要被移除的对象。
④、隐藏fragment的事务操作:
public abstract FragmentTransaction hide(Fragment fragment);
隐藏指定的fragment对象,此方法只有在指定的fragment刚好在activity的视图容器里,才会把fragment的视图隐藏起来。
⑤、显示fragment的事务操作:
public abstract FragmentTransaction show(Fragment fragment);
显示指定的fragment,这个fragment通常是被隐藏的fragment对象并且已经添加到activity的视图容器里,这样才会重新显示被影藏的fragment视图。
⑥、移除fragment视图的事务操作:
public abstract FragmentTransaction detach(Fragment fragment);
此方法用于将fragment的视图销毁,但是fragment仍然是可用的,可通过fragmentManager重新复用(在FragmentManager里面其实保存了一个栈,存放了很多fragment事务)。
⑦、附加fragment视图的事务操作:
public abstract FragmentTransaction attach(Fragment fragment);
⑧、设置在此事务中所有fragment的显示显现动画:
public abstract FragmentTransaction setCustomAnimations(int enter, int exit)
⑨、提交事务的操作:
public abstract int commit();
将事务操作提交,此操作不会立即出发事务的执行,而是会进行排队等待,当线程准备好了才会执行,且必须是在主线程中调用这个方法。此方法必须在包含fragment的activity保存状态之前调用,否则的话会抛出异常。因为在保存状态之后调用commit方法,此fragment的状态就无法得到保存,对于activity恢复状态(比如配置改变了)来说就会发生错误。
细心的读者可以发现,上面所说的所有方法都是抽象方法,也就是说并不能直接被我们所用,那是不是说需要我们自己去实现呢。其实不是的,上面提到的这个方法只是为后面做铺垫。我们真正用于操控fragment的类是FragmentManager,FragmentManager方法有一个实现类叫做FragmentManaegerImpl,这个类里面包含了一个实现了FragmentTransaction的BackStackRecord类,后续的很多操作都是调用这个类来执行fragment的事务操作的。下面介绍一下FragmentManager。
⑩、将事务压入后退栈的操作:
public abstract FragmentTransaction addToBackStack(String name)
fragment的事务可以被压入后退栈(activity维护的一个用于保存fragmentd的事务操作的栈),在执行了commit方法之后,此事务就会被押入栈,之后,我们在按返回键返回的时候,此事务就会出栈并会还原成上次的视图状态出现在用户面前。
参数解析:
name:与当前事务相关的名字,可以为null。
二、FragmentManager
FragmentManager是一个抽象类,里面包含了大量的与Activity中的Fragment进行交互的接口,也是我们直接打交道的进行管理Fragment的类。对于这个类,有以下几点要注意:
①、开始一个Fragment事务。
public abstract FragmentTransaction beginTransaction()
此方法用于启动一系列与当前FragmentManager相关联的Fragment的编辑操作。注意Fragment事务的创建和提交都必须在activity保存状态之前调用(Acitivty.onSaveInstanceState之前),否则会报错。因为fragment的状态也是要保存的。
②、立即执行事务操作:
public abstract boolean executePendingTransactions();
前面说过,事务调用commit方法之后,不是立即执行的,而是会在线程里等待执行。如果需要立即执行的话,就可以调用此方法。此方法必须在主线程里面调用。
③、查找Fragment:
public abstract Fragment findFragmentById(int id);
public abstract Fragment findFragmentByTag(String tag);
对于FragmentManger的比较重要的方法就是这些了,因为这里边的大部分实现都是围绕着FragmentTransaction来开展的,也就是说,了解了FragmentTransaction各个方法的目的就可以实现基本的操作了。下面开始了解Fragment大家族。对于Fragment来说,主要了解它的生命周期和一些需要注意的点就可以了。另外就是需要了解ListFragment,WebViewFragment,DialogFragment的特性以及使用方法。最后会通过一个综合的例子来介绍如何应用。
三、Fragment
四、ListFragment
<?xml version="1.0" encoding="utf-8"?> * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" * android:orientation="vertical" * android:layout_width="match_parent" * android:layout_height="match_parent" * android:paddingLeft="8dp" * android:paddingRight="8dp"> * * <ListView android:id="@id/android:list" * android:layout_width="match_parent" * android:layout_height="match_parent" * android:background="#00FF00" * android:layout_weight="1" * android:drawSelectorOnTop="false"/> * * <TextView android:id="@id/android:empty" * android:layout_width="match_parent" * android:layout_height="match_parent" * android:background="#FF0000" * android:text="No data"/> * </LinearLayout>
每一项数据的布局文件可通过设置Adpter的时候设置,这个 后面来讲。主要方法盘点:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(com.android.internal.R.layout.list_content, container, false); }
可以看到,如果没有自定义布局的需要,我们根本不需要重写这个方法,但是如果我们有这个需求,就必须重写这个方法,并且布局必须含有一个id为@id/android:list的listView,如果希望数据为空的时候,显示提示视图,那么只要将该视图的id设为@id/android:empty即可。
public void onListItemClick(ListView l, View v, int position, long id) { }
public void setListAdapter(ListAdapter adapter) {
注意必须是ListAdapter的子类,如果对于Adapter不是很了解,可以参考Adapter大家族详解。每项数据的样式也是通过adpter设置的。
五、WebViewFragment:
六、DialogFragment:
接下来使用一个综合运用了上述所有知识的例子来讲述具体的用法。下面这个例子是关于显示数字的。当处于竖屏模式的时候,会显示一个显示1-10的数字列表,点击其中一个就会跳转到另一个activity显示相应的数据。当时横屏模式的时候,会显示一个有两个fragment的activity ,单击左边的数据会在右边显示出来。
<resources> <string name="app_name">fragment</string> <string-array name="number"> <item>1</item> <item>2</item> <item>3</item> <item>4</item> <item>5</item> <item>6</item> <item>7</item> <item>8</item> <item>9</item> <item>10</item> </string-array></resources>
布局文件分为竖屏模式和横屏模式,先看目录结构:
layout/activity_main.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" tools:context="com.cw.fragment.MainActivity"> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"></FrameLayout></LinearLayout>
<?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="horizontal" android:weightSum="2" tools:context="com.cw.fragment.MainActivity"> <FrameLayout android:id="@+id/container" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"></FrameLayout> <fragment android:id="@+id/rightFragment" android:name="com.cw.fragment.RightFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" tools:layout="@layout/right_layout" /></LinearLayout>
layout/right_layout:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#efefef" android:gravity="center" android:orientation="vertical"> <TextView android:id="@+id/content" android:layout_width="match_parent" android:layout_height="30dp" android:gravity="center" android:text="内容" /></LinearLayout>
接着定义RightFragment:
package com.cw.fragment;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;/** * Created by Myy on 2016/7/28. */public class RightFragment extends Fragment { private View view; private TextView textView; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.right_layout, null); textView = (TextView) view.findViewById(R.id.content); return view; } public void setContent(int i) { textView.setText(i + ""); }}
package com.cw.fragment;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.widget.TextView;/** * //用于单Fragment * Created by Myy on 2016/7/28. */public class RightActivity extends AppCompatActivity { private TextView textView; private RightFragment fragment; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); fragment = new RightFragment(); getSupportFragmentManager().beginTransaction().add(R.id.container, fragment).commit(); } @Override protected void onStart() { super.onStart(); int i = getIntent().getIntExtra("position", 0); fragment.setContent(i); }}
最后是mainActivity:
package com.cw.fragment;import android.content.Intent;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentTransaction;import android.support.v4.app.ListFragment;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.ListAdapter;import android.widget.ListView;import java.util.Arrays;import java.util.List;public class MainActivity extends AppCompatActivity { private List<String> numbers = null; //注意包的引用 private ListFragment leftFragment; private RightFragment rightFragment; private ListView listView; private boolean isTwoPage = false;//用于判断是否是双fragment模式,在这里竖屏模式设为双fragment模式 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); numbers = Arrays.asList(getResources().getStringArray(R.array.number)); initListFragment(); FragmentManager manager = getSupportFragmentManager(); rightFragment = (RightFragment) manager.findFragmentById(R.id.rightFragment);//当加载的是layout-land布局的fragment才不为null if (rightFragment != null) isTwoPage = true; FragmentTransaction transaction = manager.beginTransaction(); transaction.add(R.id.container, leftFragment); transaction.commit(); // transaction.addToBackStack(null);可以将此事务添加进后退栈里面 //fragment调用activityd的方法。通过getActivity() //acitivty调用fragment的方法。getFragmentManager().findFragmentById() } @Override protected void onStart() { super.onStart(); listView = leftFragment.getListView(); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (isTwoPage) rightFragment.setContent(position + 1); else { Intent intent = new Intent(MainActivity.this, RightActivity.class); intent.putExtra("position", position+1); startActivity(intent); } } }); } private void initListFragment() { leftFragment = new ListFragment(); ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, android.R.id.text1, numbers); leftFragment.setListAdapter(adapter); }}
上述可以看到用ListFragment添加到左边的Framelayout布局,使用了事务添加操作。
看看竖屏模式的效果:
点击:
切换竖屏模式:
点击:
如上,请读者好好体会这个例子,可以发现fragment和activity的异同以及事务使用的方法。
---------文章写自:HyHarden---------
--------博客地址:http://blog.csdn.net/qq_25722767-----------
- fragment的使用以及fragment大家族解析
- ViewPager与support包里的Fragment家族一起使用
- Android Fragment解析以及Fragment中碰到的各种坑
- (4)Fragment家族常用的API
- Fragment嵌套Fragment使用存在的一些BUG以及解决方法
- Fragment深度使用解析
- Fragment 使用解析
- Fragment的生命周期以及使用技巧
- ViewPager+Fragment以及GridView的使用
- 使用Fragment出现的问题解析
- Fragment的解析与使用(一)
- Fragment的解析和使用(二)
- android的fragment解析
- Fragment的详细解析
- Activity与Fragment,以及Fragment与Fragment之间的数据通讯
- Fragment的生命周期,以及fragment用hide和show,以及放在Viewpager中的使用
- 解析Fragment
- Fragment解析
- Java关键字--final
- PAT1084
- 关于友谊
- 今天开始重新更新(ps:广接各种php相关的外包项目,有意者请留言或者私聊)
- 文章标题
- fragment的使用以及fragment大家族解析
- PYTHON黑帽编程1.5 使用WIRESHARK练习网络协议分析
- 图片防盗链
- ROS by example -第十二章 DYNAMIXEL 伺服系统和 ROS
- UVA1225 UVALive3996 Digit Counting
- Maven项目中使用本地JAR包
- Activiti介绍
- Trie树的DAT实现
- Spring依赖注入详解