首页 新闻 会员 周边

请问在fragment中,onCreateView所返回的view是否可以动态修改

0
悬赏园豆:20 [待解决问题]

我的fragment里面有个自定义的横向滚动控件,里面的item需要动态变化,使用adapter.notifydatachange(里面setImgResourse(R.id.xx))并不能刷视图,在两个fragment切换时却可以,我觉得应该是fragment在oncreateview()返回的view的问题。请问有什么方法可以刷新该fragment返回的view。

  

< >
分享
所有回答(2)
-1

http://q.cnblogs.com/q/58040/

博学多思 | 园豆:76 (初学一级) | 2015-10-30 11:25

已经看过了 并不能解决

支持(0) 反对(0) xcheng名字已存在 | 园豆:182 (初学一级) | 2015-10-30 13:02

@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.   Fragmentback

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

 

发表评论
 文明上网,理性发言
  • 网友评论 (0)
  • 暂无网友评论
支持(0) 反对(0) 博学多思 | 园豆:76 (初学一级) | 2015-10-30 13:05

请问如何在button.onclickListener中刷新当前fragment,使fragment重新绘制界面?

我是个新手 有很多不懂得地方,您发的我都搜到过,可就是不懂。麻烦能详细说明下。

支持(0) 反对(0) xcheng名字已存在 | 园豆:182 (初学一级) | 2015-10-30 13:12

@xcheng名字已存在: http://stackoverflow.com/questions/9889175/is-it-possible-to-refresh-the-view-of-a-fragment

支持(0) 反对(0) 博学多思 | 园豆:76 (初学一级) | 2015-10-30 13:13

@xcheng名字已存在: 解决了?没解决还有

支持(0) 反对(0) 博学多思 | 园豆:76 (初学一级) | 2015-10-30 13:30
0

楼主,你好!看了你的问题描述,并不能完全理解你的问题所在。看字面上意思,你应该有不只1个fragment,并需要在A fragment 里面的 button.onclickListener 去 动态 刷新 A fragment 里面的 ListView ?(因为看到了adapter),实际上却刷新失败?但是在A fragment和B fragment 切换的时候,是可以刷新的 ......这是你大致的意思。我假设你使用了ListView,你先确保一下数据源 是否被 重定向,比如 一个数组字符串 是你的数据源,adapter 把这个数据源 关联,然后 listview  设置adapter ,此时,数据源 不要再指向其他的引用..........你最好贴出你的代码,不然不知道你要表达的问题

sooglejay | 园豆:204 (菜鸟二级) | 2015-11-14 18:11
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册