我的fragment里面有个自定义的横向滚动控件,里面的item需要动态变化,使用adapter.notifydatachange(里面setImgResourse(R.id.xx))并不能刷视图,在两个fragment切换时却可以,我觉得应该是fragment在oncreateview()返回的view的问题。请问有什么方法可以刷新该fragment返回的view。
http://q.cnblogs.com/q/58040/
已经看过了 并不能解决
@xcheng名字已存在:
Fragment 简单操作
骑着乌龟的蜗牛 发布于 11个月前,共有 0 条评论
Fragment
l Fragment 介绍
Fragment允许将Activity拆分成多个独立封装的可重用的组件,每个组件有它自己的生命周期和UI布局。
Fragment最大的优点是你可以为不同屏幕大小的设备创建灵活的UI。
每个Fragment都是独立模块,并与它所绑定的Activity紧密联系在一起的。多个Activity可以共用一个Fragment,对于平板电脑这种一个界面有很多的UI模块的设备,Fragment展现了极好的适应性和动态构建UI的能力,可以在一个正在显示的Activity中添加、删除、更换Fragment(add(),remove(),detele())。Fragment可以响应自己的输入事件,并且有自己的生命周期,当然,它们的生命周期直接被其所属的宿主activity的生命周期影响。
Fragment为大量的不同型号、尺寸、分辨率的设备提供了一种统一的UI优化方案。
尽管没有必要将Activity(及相关布局)分解成多个Fragment,但是这样做将极大的提高UI的灵活性,并更容易为一些新的设备配置带来更好的用户体验。
Android在3.0中引入了fragments的概念,主要目的是用在大屏幕设备上--例如平板电脑上,支持更加动态和灵活的UI设计。平板电脑的屏幕要比手机的大得多,有更多的空间来放更多的UI组件,并且这些组件之间会产生更多的交互。Fragment允许这样的一种设计,而不需要你亲自来管理 viewhierarchy的复杂变化。 通过将activity的布局分散到fragment中, 你可以在运行时修改activity的外观,并在由activity管理的back stack中保存那些变化.
例如, 一个新闻应用可以在屏幕左侧使用一个fragment来展示一个文章的列表,然后在屏幕右侧使用另一个fragment来展示一篇文章--2个fragment并排显示在相同的一个activity中,并且每一个fragment拥有它自己的一套生命周期回调方法,并且处理它们自己的用户输入事件。 因此, 取代使用一个activity来选择一篇文章而另一个activity来阅读文章的方式,用户可以在同一个activity中选择一篇文章并且阅读, 如图所示:
1.创建Fragment
通过继承Fragment类或者继承已知的Fragment子类。可以重定义改Fragment的UI的或者实现Fragment类封装的方法。
大多数情况下,需要为Fragment分配一个UI,也可以为一个Activity创建一个没有任何UI的但提供后台行为的Fragment。
如果Fragment需要UI,可以重写onCreateView方法来填充并返回所需要的View层次。和Activity不同的,Fragment不需要再manifest中进行注册,因为Fragment只是Activity的一部分,只有Fragment 嵌入到Activity中时,它才能存在,它的生命周期也依赖于它所嵌入的Activity。
2.Fragment的生命周期
Fragment类看起来跟Activity类很相似,都有类似的回调方法;Fragment的生命周期事件镜像它的父Activity的生命周期事件,但是包含它的Activity进入到active-resumed 状态的时候,添加或者删除一个fragment就会影响到它自己的生命周期。
Fragment包含一系列和Activity想象的事件处理程序,当Fragment 创建、启动、恢复、暂停、停止和销毁时,这些事件处理程序就会被触发。Fragment 还包含一些额外的callback,用来标示,Fragment和它的父Activity之间的绑定和解绑定关系、Fragment的View层次的创建(和销毁)情况,以及它的父Activity的创建过程的完成情况。
以上是Fragment的生命周期,通常, 应当至少实现如下的生命周期方法:
onCreate()
当创建fragment时, 系统调用该方法. 在实现代码中,应当初始化想要在fragment中保持的必要组件, 当fragment被暂停或者停止后可以恢复.
onCreateView()
fragment第一次绘制它的用户界面的时候, 系统会调用此方法. 为了绘制fragment的UI,此方法必须返回一个View, 这个view是你的fragment布局的根view. 如果fragment不提供UI, 可以返回null.
onPause()
用户将要离开fragment时,系统调用这个方法作为第一个指示(然而它不总是意味着fragment将被销毁.) 在当前用户会话结束之前,通常应当在这里提交任何应该持久化的变化(因为用户有可能不会返回).
public class FragmentLifeCycle extends Fragment { /********调用该方法时Fragment会连接到它的父Activity上*******/ //Called when a fragment is first attached to its activity. @Override public void onAttach(Activity activity) { //获取对父Activity的引用 super.onAttach(activity); } /********调用该方法来进行Fragment的初始化创建**********/ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //初始化Fragment } /*********一旦Fragment创建,要创建它自己的界面时调用此方法************/ //Called to have the fragment instantiate its user interface view @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { //创建或者填充Fragment的UI,并返回它,如果Fragment没有UI就返回null return super.onCreateView(inflater, container, savedInstanceState); } /*********一旦父Activity和Fragment的UI已被创建 ,则调用此方法************/ @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); //完成Fragment的初始化 //尤其是那些父Activity被初始化完成后,或者Fragment的View被完全填充后才能做的事情 } /******* 当Fragment 可见时调用********/ // Called when the Fragment is visible to the user. @Override public void onStart() { super.onStart(); } /********当Fragment 可见并且 已经处于活跃状态 时调用************/ //Called when the fragment is visible to the user and actively running. @Override public void onResume() { super.onResume(); //恢复所有暂停的Fragment需要的UI更新,线程或者进程,但是非活动状态它是暂停的 } /********调用此方法来询问fragment 保存UI动态变化,所以可以在之后重新启动时对它重建*********/ //Called to ask the fragment to save its current dynamic state, //so it can later be reconstructed in a new instance of its process is restarted. @Override public void onSaveInstanceState(Bundle outState) { //将UI的状态的改变信息保存到 Bundle outState, //如果它的父Activity被终止并重新启动,这个Bundle会被传递到onCreate、 onCreateView和onActivityCreate方法中 super.onSaveInstanceState(outState); } /*********在Fragment不在继续活动**********/ //Called when the Fragment is no longer resumed. @Override public void onPause() { //当Activity不是活动的前台Activity时, //需要暂停UI的更新、挂起线程或者暂停那些不需要更新的CPU的密集的处理流程 //由于调用这个方法后,进程可能会被终止,所以要保存所有的编辑和状态改变信息 super.onPause(); } /******** Fragment不在可见时调用 ,通常跟父Activity生命周期中的onStop 绑定在一起 *********/ //Called when the Fragment is no longer started. //This is generally tied to Activity.onStop of the containing Activity's lifecycle @Override public void onStop() { super.onStop(); //当Fragment不可见时,暂停其余的UI更新、挂起线程或者暂停不再需要的处理 } /*********当Fragmentde View 被分离时调用********/ @Override public void onDestroyView() { super.onDestroyView(); //清除跟View相关的资源 } /********当Fragment不可用时调用*******/ //Called when the fragment is no longer in use. @Override public void onDestroy() { super.onDestroy(); //清理所有资源 //包括结束线程和关闭数据库连接等 } /************当Fragment从它的父Activity上分离时调用**********/ //Called when the fragment is no longer attached to its activity. @Override public void onDetach() { // TODO Auto-generated method stub super.onDetach(); } }
1. Fragment 特有的生命周期事件
从父Activity中绑定和分离Fragment
Fragment的生命周期开始于绑定到它的父Activity,结束于从父Activity上分离。通过分别调用onAttach 和 onDetach 来表示绑定 和 分离。
在Fragment/Activity被暂停之后,由于任何其他处理程序都可以被调用,可能会出现它的父Activity进程没有完成它的全部生命周期被终止从而导致onDetach不会被调用的情况。
onAttach事件在Fragment的UI被创建之前,以及Fragment自身或它的父Activity完成它们的初始化之前会被触发。通常情况下,onAttach事件用来获取一个Fragment的父Activity的引用,为进一步初始化工作做准备。
创建和销毁Fragment
已创建的Fragment的生命周期存在于首次对onCreate的调用和最终onDestroy的调用的期间。对于Activity来说在没有调用onDestroy方式而被终止的情况很多见。所以Fragment不能依赖触发onDestroy方法来销毁它。
与Activity一样,应该使用onCreate方法初始化Fragment,在Fragment生命周期内创建的任何类作用域对象,最好确保它们能只被创建一次。
创建和销毁用户界面
Fragment的UI是在一套新的事件处理程序中初始化和销毁的:分别是onCreateView和
onDestroyView。
使用onCreateView方法来初始化Fragment :填充UI、获取它所包含的View的引用
(绑定到该View的数据),然后创建所需的任何的Service 和Timer;
一旦已经填充好了View层次,该View也能改从这个处理程序返回:
return inflater.inflate(R.layout.my_fragment, container,false);
如果Fragment需要和它的父Activity的UI交互,需要一直等到onActivityCreated事件被触发。该事件被触发意味着Fragment所在的Activity已经完成了初始化并且它的UI也已经完全构建好了。
2. Fragment状态
和Activity一个样,当fragment所属的Activity处于前台并拥有焦点是,这些Fragment也是活动的。当Activity被暂停或停止,它所包含的Fragment也会被暂停和停止,一个非活动的Activity包含的Fragment 也是非活动的。当Activity最总被销毁时,它所包含的每一个Fragment同样也会被销毁。
3. Fragment Manager 介绍
每一个Activity都包含一个FragmentManager来管理它所包含的的Fragment.可以通过
getFragmentManager()来访问FragmentManager:
FragmentManager fragmentManager = getFragmentManager();
Fragment Manager 提供了很多方法用来访问当前添加到Activity上的Fragment、通过执行Fragment Transaction来添加、删除和替换Fragment。
4. 向Activity中添加Fragment
想要把一个Fragment添加到一个Activity中,最简单的方法是在Activity布局中使用fragment标签来包含它,例如:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:name="com.paad.weatherstation.MyListFragment" android:id="@+id/my_list_fragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> <fragment android:name="com.paad.weatherstation.DetailsFragment" android:id="@+id/details_fragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="3" /> </LinearLayout> 一旦一个Fragment被填充后,它就成为一个ViewGroup ,会在Activity 内显示和管理它所包含的UI。 当使用Fragment基于不同屏幕尺寸来定义一系列静态布局时,该技术是行之有效的。如果打算在运行时添加、删除、或者替换Fragment的方式来动态的修改布局,更好的方法是基于当前的应用程序状态来使用容器View来创建布局,Fragment可以在运行时放入到一个容器View内。 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/ui_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> <FrameLayout android:id="@+id/details_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="3" /> </LinearLayout>
5. 使用Fragment Transaction
在运行时,Fragment Transaction可以用来在一个Activity内添加、删除、和替换Fragment。使用FragmentTransaction,可以让布局变得动态。而且FragmentTransaction同样支持显示过度动画的规范以及是否在back栈中包含Transaction。
一个新的FragmentTransaction 是通过Activity的FragmentManager中的beginTransaction方法创建的。在设置显示动画前,可以根据要求使用add,、remove、replace方法来修改布局,并设置恰当的back栈行为。当准备执行改变时,调用commit方法将事务添加到UI队列。
FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); //添加、删除、替换 Fragment //指定动画 //如果需要的话可以添加到back栈中 fragmentTransaction.commit();
6. 添加、删除、替换 Fragment
添加一个新的UIFragment时,需要制定添加的Fragment 实例和将要放置它的容器View。另外还可以为这个Fragment制定一个tag标识,后面通过标识,可以使用findFragmentByTag方法找到Fragment。
fragmentTransaction.add(R.id.ui_container, new myFragment());
fragmentTransaction.commit();
删除一个Fragment,首先要找到这个Fragment的引用,通常可以通过FragmentManager的findFragmentById或者findFragmentByTag方法来实现。然后把找到的Fragment实例作为参数传给FragmentTransaction的remove方法。
Fragment fragment = fragmentManager.findFragmentById(R.id.details_fragment); fragmentTransaction.remove(fragment); fragmentTransaction.commit();
类似的还可以把一个Fragment替换(replace)为另一个,指定要替换的Fragment的父容器的Id、一个替换它的新Fragment和新Fragment的tag标识(可选)。
fragmentTransaction.replace(R.id.details_fragment, new DetailsFragment()); fragmentTransaction.commit();
7. 使用FragmentManager查找Fragment
想要在Activity中查找Fragment,可以使用FragmentManager;
通过xml布局的方式把Fragment加到Activity中的,可以这样查找
MyFragment myFragment =(MyFragment)fragmentManager.findFragmentById(R.id.myfragment);如果已经通过FragmentTransaction添加了一个Fragment,应该把容器View的资源标识符指定给要添加了的想要查找的Fragment。另外,还可以通过使用findFragmentByTag来查找在FragmentTransaction中指定了tag标识的Fragment。
MyFragment myFragment =(MyFragment)fragmentManager.findFragmentByTag(MyFRAGMENT_TAG);
8. 使用Fragment填充动态的Activity布局
如果在运行时动态改变Fragment的结构和布局,最好在XML布局中只定义父容器,并在运行时使用FragmentTransaction来单独填充它,从而当因配置改变(如屏幕旋转)而引起的UI重新创建时,能够确保一致性。代码如下:
public class MyFragmentActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Inflate the layout containing the Fragment containers setContentView(R.layout.fragment_container_layout); FragmentManager fm = getFragmentManager(); // Check to see if the Fragment back stack has been populated // If not, create and populate the layout. DetailsFragment detailsFragment = (DetailsFragment)fm.findFragmentById(R.id.details_container); if (detailsFragment == null) { FragmentTransaction ft = fm.beginTransaction(); ft.add(R.id.details_container, new DetailsFragment()); ft.add(R.id.ui_container, new MyListFragment()); ft.commit(); } } }
首先检查这个UI是否根据之前的状态已经被填充过了,为了确保用户体验的一致性,当Activity因配置改变而重新启动时,Android会保存Fragment布局和关联的Back栈。
因为同样的原因,当因运行时配置改变而创建可替代的布局时,最好考虑在所有的布局变化中,包含所有事务所包含的所有的View容器。这样做的坏处是会导致FragmentManager试图吧Fragment还原到已不在的新布局中的容器。
在一个给定方向的布局中删除一个Fragment容器,只需要简单的将布局定义的改Fragment的visibility属性设置为gone即可。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/ui_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> <FrameLayout android:id="@+id/details_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="3" /> </LinearLayout>
9. Fragment和back栈
Fragment能够创建动态的Activity布局,这些布局可以被修改来使UI发生重大改变。在某些情况下这些改变可以被视为一个新的屏幕——在这些情况下,用户可能会理所当然的期望Back按键会返回到前一个布局。同样包括回滚前一个已执行的Fragment Transaction。
Android提供方便的技术。想要将FragmentTransaction添加到back栈,可以在调用commit方法之前,在FragmentTransaction中调用addToBackaStack方法。
FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.add(R.id.ui_container, new MyListFragment()); Fragment fragment = fragmentManager.findFragmentById(R.id.details_container); fragmentTransaction.remove(fragment); String tag = null; fragmentTransaction.addToBackStack(tag); fragmentTransaction.commit();
当按下back键时,之前的FragmentTransaction将会回滚并且UI将返回到之前的布局。
当上文所述的FragmentTransaction已被提交,Details Fragment 就会被停止并且被移动到back栈中而不是简单的被销毁。如果Transaction回滚,ListFragment被销毁,Detailfragment 就会被重新启动。
10. 是FragmentTransaction动起来
想要应用众多的默认过渡动画中的一个,可以对任何FragmentTransaction使用setTransaction方法,并传入一个FragmentTransaction.TRANSIT_FRAGMENT_*常量:
transaction.setTransation(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
也可以通过使用setCustomAnimations方法对FragmentTransaction应用自定义动画。这个方法接受两个XML:一个是通过该事物添加到布局的Fragment,而另一个是被删除的Fragment:
transaction.setCustomAnimations(R.animator.slide_in_left,R.animator.slide_out_right);
当在布局内替换Fragment时,这种方式对于添加无缝动态过渡尤其有用。
11. Fragment和Activity之间的接口
在任何Fragment中使用getActivity方法返回它所嵌入的Activity的引用。这对于查找当前上下文、使用FragmentManager访问其他Fragment和在Activity的View层次中查找View尤其有用。
TextView textView = (TextView)getActivity().findViewById(R.id.textview);
尽管Fragment可以直接使用主Activity的FragmentManger进行通信,但通常最好考虑使用Activity来做媒介。这样会让Fragment尽可能独立和松耦合,而Fragment 的职责在与决定Fragment中的一个事件应该如何影响主Activity的整体UI性能下降。
在Fragment需要和他的主Activity共享事件的地方(如提示UI选中),最好在Fragment中创建一个callBack接口,而主Activity必须实现它。
重写onAttach处理程序用来获取主Activity的引用,并确保主Activity实现了必要的接口。
public class TestFragment extends Fragment{ public interface OnTestSelectedListener{ public void onTestSelected(Test test); } private OnTestSelectedListener onTestSelectedListener; private Test test; @Override public void onAttach(Activity activity) { super.onAttach(activity); try{ onTestSelectedListener = (OnTestSelectedListener) activity; }catch(ClassCastException e){ throw new ClassCastException(activity.toString()+"must implement OnTestSelectedListener"); } } private void setTest(Test test){ test = test; onTestSelectedListener.onTestSelected(test); } }12. 没有界面的Fragment
在大部分情况下,Fragment用来封装UI的模块化的组件;然而,也可以创建没有UI的Fragment来提供后台行为,该行为会一直持续到Activity重写启动,这特别适合于定期和UI交互的后台任务或者当因配置改变而导致的Activity重新启动时,保存状态变得特别重要的场合。
当Fragment的父Activity重新创建时,可以选择使用Fragment的setRetainInstance方法让一个活动的Fragment保留它的实例。调用该方法之后,Fragment的生命周期会改变。
当Activity重新启动时,同一个Fragment的实例会被保留下来,而不是和它的父Activity一起被销毁和重新创建。但Fragment所在的Activity被销毁时,将会受到onDetach事件,之后当新的父Activity实例化后,还会接收到onAttach、onCreateView和onActivityCreated事件。
虽然可以对存在UI的Fragment使用这项技术,但一般不建议这样做。更好的选择是把关联的后台任务活必要的状态移入新的没有UI的Fragment中,根据需要让两个Fragment交互。
public class NewItemFragment extends Fragment { @Override public void onAttach(Activity activity) { super.onAttach(activity); //获得父Activity的类型安全的引用 } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //创建后台工作线程和任务 } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); //初始化工作线程和任务 } }
要把Fragment加入到Activity中,必须创建一个新的Fragment Transaction ,并指定一个tag 来标识改Fragment 。因为该Fragment没有UI,所以它不应该和一个View容器关联而且通常不应该被添加到back栈中。
FragmentManager fm = getFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); ft.add(workerFragment, MY_FRAGMENT_TAG); ft.commit();之后,通过FragmentManager的findViewByTag获取它的一个引用。
MyFragment myFragment = fm.findFragmentByTag(MY_FRAGMENT_TAG);
13. Android Fragment 类
Android SDK封装很多Fragment子类,这些子类封装了最常见的Fragment实现。其中一些比较有用的:
l DialogFragment
l ListFragment
l WebViewFragment
更多参见:(http://developer.android.com/guide/topics/fundamentals/fragments.html)
请问如何在button.onclickListener中刷新当前fragment,使fragment重新绘制界面?
我是个新手 有很多不懂得地方,您发的我都搜到过,可就是不懂。麻烦能详细说明下。
@xcheng名字已存在: http://stackoverflow.com/questions/9889175/is-it-possible-to-refresh-the-view-of-a-fragment
@xcheng名字已存在: 解决了?没解决还有
楼主,你好!看了你的问题描述,并不能完全理解你的问题所在。看字面上意思,你应该有不只1个fragment,并需要在A fragment 里面的 button.onclickListener 去 动态 刷新 A fragment 里面的 ListView ?(因为看到了adapter),实际上却刷新失败?但是在A fragment和B fragment 切换的时候,是可以刷新的 ......这是你大致的意思。我假设你使用了ListView,你先确保一下数据源 是否被 重定向,比如 一个数组字符串 是你的数据源,adapter 把这个数据源 关联,然后 listview 设置adapter ,此时,数据源 不要再指向其他的引用..........你最好贴出你的代码,不然不知道你要表达的问题