zoukankan      html  css  js  c++  java
  • Fragment

     阅读过程中有疑惑的地方:

    • inflate方法的第三个参数,为true和false时,到底有何区别;
    • FragmentTransaction的replace方法,到底是怎么个替换法?是把当前view中所有fragment都替换掉,还是只替换id相同的fragment;
    • FragmentTransaction的addToBackStack()方法,是返回上一次状态,但是为何平板上面实际操作的时候是直接退出了activity;
    • padding的单位,按我的理解,只能是像素吧;
    •  

      发现了一个自适应计算的方法:TypedValue.applyDimension,方法源码如下:

     

     1 public static float applyDimension(int unit, float value,
     2                                        DisplayMetrics metrics)
     3     {
     4         switch (unit) {
     5         case COMPLEX_UNIT_PX:
     6             return value;
     7         case COMPLEX_UNIT_DIP:
     8             return value * metrics.density;
     9         case COMPLEX_UNIT_SP:
    10             return value * metrics.scaledDensity;
    11         case COMPLEX_UNIT_PT:
    12             return value * metrics.xdpi * (1.0f/72);
    13         case COMPLEX_UNIT_IN:
    14             return value * metrics.xdpi;
    15         case COMPLEX_UNIT_MM:
    16             return value * metrics.xdpi * (1.0f/25.4f);
    17         }
    18         return 0;
    19     }

     

      根据当前value以及单位、屏幕密度来动态计算,返回的值是计算过后的实际像素。

      实例:

     

    1  int padding = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
    2                     4, getActivity().getResources().getDisplayMetrics());
    3  text.setPadding(padding, padding, padding, padding);

     

      dp实际上可以理解成一个相对的比例,比如若在mdpi、分辨率是480x800的屏幕上面,一个宽240dp的按钮,实际像素是240px,占了屏幕的1/2;那么在ldpi、分辨率是320x480的屏幕上面,它也要占屏幕的1/2,但是button的像素只有160px了。

      阅读完以后的总结:

    • 设计原则,为什么要用fragment
    • 创建方式,包括两种,一种是通过xml文件夹,另外一种是在代码中添加
    • 如何管理
    • 与activity如何交互

     

    一、设计原则
      fragment是为了使大屏幕的界面更加灵活而产生,将UI抽象成可重用的组件,然后在界面上灵活使用。最常见的用法是在横竖屏切换、或者平板与手机共用同一个apk的时候,如下图:

    Fragment - 笨小孩 - 我要当地主

     

     

     

    应用场景1

      个人理解:平板横屏的时候,可以将左侧的列表和右侧的详细信息同时展现出来;竖屏的时候宽度不够,那么只是单独展示列表或者详细信息。常规的做法是需要针对这种方式分别写上3个activity.那么使用fragment后,将列表抽象成一个共用的fragment,详细信息也抽象成一个公用的fragment,横屏的布局文件中包含两个fragment,竖屏的只包含一个fragment,但是共用同一个activity A的代码。需要做的判断是在点左侧列表中一个选项的时候,是在右侧更新内容还是另起一个activity来展示。另起的activity B 只要将fragment B包含进去即可,并不需要新增很多再处理的代码,这样就达到了一个重用的效果。

     

    二、创建

     

      fragment的生命周期是受其依附的activity影响,当activity暂停或者停止时,fragment也会同时达到相应的状态。当activity出于运行状态时,fragment才会进入自由的一个生命周期。

     

      其中,比较重要的生命周期方法包括:

    • onCreateView:在onCreate之后,用于返回fragment的根视图对象,一般使用InflateLayout.inflate方法,从xml资源文件转换成View对象。
    • onActivityCreated:在其依附的activity的onCreate方法成功返回后触发,用于做进一步操作,比如创建一个接口用于回调给activity,这时候可以检验activity是否实现了该接口。
    1. 创建方式

     

      包括两种,一种是直接在xml文件中做配置:  

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:orientation="horizontal"
     4     android:layout_width="match_parent"
     5     android:layout_height="match_parent">
     6     <fragment android:name="com.example.news.ArticleListFragment"
     7             android:id="@+id/list"
     8             android:layout_weight="1"
     9             android:layout_width="0dp"
    10             android:layout_height="match_parent" />
    11     <fragment android:name="com.example.news.ArticleReaderFragment"
    12             android:id="@+id/viewer"
    13             android:layout_weight="2"
    14             android:layout_width="0dp"
    15             android:layout_height="match_parent" />
    16 </LinearLayout>

      其中的name属性实际就是具体指定fragment的实例,id和tag两个属性都可以用来标识fragment,但是一般用id;若是无界面的fragment,则用tag来标识。

      另外一种是在代码中动态的添加:  

    1 FragmentManager fragmentManager = getFragmentManager()
    2 FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    3 fragmentTransaction.add(R.id.replace);

       其中的R.id.fragment_container可以看作成是定义好的fragment容器,也即是xml中定义的fragment节点,但是没有指定过name或者class属性;是否也可以看作成一个任意的ViewGroup对应的资源Id?两者取其一还是都可以? 

     

      2. 管理fragment

      主要是通过FragmentManager对象来操作,主要负责:

    • 创建transaction,进行fragment的添加、删除、替换等事物操作;
    • 查找fragment,这个fragmentManager对象的引用是否依附于activity中的,通过getFragmentManager()方法可以直接获取该对象。通过findFragmentById获取findFragmentByTag来查找当前activity下存在的fragment;
    • 执行返回键的操作,出栈已存放的fragment事物;

      transaction提交之前的所有添加删除操作看成一个事物,当调用addToBackStack方法后,会将之前所有发生的改变看作一次改变,再返回回来的时候,是展示所有这改变之前的状态。

      3. 与activity进行交互

      fragment毕竟是独立出来的组件,那么fragment中发生的操作如何让activity也捕捉到呢?activity又如何向fragment传送值呢?

      让activity捕捉到,无非就是在fragment中触发某种操作后,比如点击按钮后,然后fragment通知activity,然后activity再做出相关的响应。那么fragment如何在恰当的时候通知activity呢?sdk中提供了一种做法,在fragment中定义了一个接口,里面定义了一个方法;然后在onAttach时,判断当前依附的activity有没有实现该接口,同时引用已经实现了该接口的activity对象,用来强制实现;在fragment的比如button事件中,直接调用该引用的注册方法,通知activity来做处理。如下:

    public class Fragment_A extends Fragment{
    
      private OnChangedListener m_Listener;
    
       public interface OnChangedListener{
         public void onChanged(int index); 
      }  
    
      @Override
      public void onAttach(Activity activity){
          super.onAttach(activity);
          try{
              m_Listener=(OnChangedListener)activity;
          }catch(ClassCastException ex){
          throw new ClassCastException(activity.toString() + " 必须实现OnChangedListener!");
      }
      
    }

      Activity实现了OnChangedListener就可以接收到对应的事件,这个是不是就是传说中的监听者模式。

      那么activity如何向fragment传递数据呢?

      Fragment类包括两个方法:setArguments和getArguments。setArguments方法必须在fragment attach到activity之前调用,参数是Bundle对象;然后在fragment中调用getArguments方法,获取该fragment实例化时传递进来的Bundle对象。

      4.保存状态

      fragment的生命很大程度上会受到其依附的activity的映像,因此为了保证数据完整性,也需要在适当的时候保存下当前状态:

    1   @Override
    2         public void onSaveInstanceState(Bundle outState) {
    3             super.onSaveInstanceState(outState);
    4             outState.putInt("curChoice", mCurCheckPosition);
    5         }

       然后当该fragment再次被重新创建的时候,恢复之前保存的数据:

    1  @Override
    2         public void onActivityCreated(Bundle savedInstanceState) {
    3             super.onActivityCreated(savedInstanceState);
    4 
    5              if (savedInstanceState != null) {
    6                 // Restore last state
    7             }
    8         }

     总结:

    •   fragment的使用能够让UI更灵活
    •   感觉如何管理fragment是个关键

    其中,图片引用自 android sdk官网,转载请说明出处~~

    看不清未来,那就看脚下。
  • 相关阅读:
    逆光拍摄常见的问题(解决大光比问题)
    HDP和包围曝光
    直方图
    linux查找文件的命令【转】
    100篇大数据文章[转]
    squid
    修改/etc/resolv.conf又恢复到原来的状态?[转]
    python字符串及正则表达式[转]
    GraphLab介绍[转]
    Scala 中的 apply 和 update 方法[转]
  • 原文地址:https://www.cnblogs.com/caiwan/p/2875306.html
Copyright © 2011-2022 走看看