zoukankan      html  css  js  c++  java
  • Fragment的使用

    原文地址:http://www.cnblogs.com/kross/p/3328389.html

    新浪微博:http://weibo.com/u/1928100503

    折腾了两天,感觉有点会用了,Fragment给我的感觉就是网页上的AJAX,个人感觉,个人感觉O(∩_∩)O。

    Fragment可以当成一块视图,可以动态的添加到当前的视图中,也可以进行替换,或者删除,所以才说感觉很像AJAX。

    我做的一个demo就是google上的那个例子,显示一个列表,然后点击,页面就变成详细页,不过我是理解后按照自己的想法去实现的。下面就说下怎么操作吧。

    首先,我们需要一个Activity(activity_main.xml),用来启动的时候显示,但里面并不做任何数据的输出。布局文件如下:

    <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="vertical"
        tools:context=".MainActivity" >
        <FrameLayout
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </FrameLayout>
    </LinearLayout>

    需要注意的:里面有一个FrameLayout,属性里有一个id,这样就足够了。

    然后,我们希望程序启动后页面上显示一个列表(ListView),这个时候,需要用Fragment把列表显示出来,替换到FrameLayout上面,下面我们去实现一个显示列表的TitleFragment

    扩展Fragment的时候,有许多方法可以去覆写(Override),也可以不覆写,根据在下的学习与理解,我认为onCreateView()这个方法是返回一个视图的,也就是Fragment这个的视图,因此,如果你的Fragment是要去显示的,肯定要覆写这个方法,然后把视图返回出去。

    代码如下,一步步来:

    public class TitleFragment extends Fragment {
        
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) { 
            View v = inflater.inflate(R.layout.title_fragment, container, false);
            return v;
        }
    }

     需要注意的是LayoutInflater.inflate()这个方法,很长一段时间,我都木有理解什么叫所谓的“扩充布局”,后来去stackoverflow网站上去找找,老外说:扩充布局这是java里面的一个惯用的说法。实际上就是将一个布局文件(xml)变成一个View对象,在下是这样理解的。Activity中有一个setContentView()的方法,应该也是将布局文件转成一个View对象,然后给Activity设置上。

    如上的代码就是要让onCreateView返回一个View对象啦,当然我们这个TitleFragment对象是要显示一个列表的,所以布局中应该有一个ListView的吧,看看布局文件title_fragment.xml

    <?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:orientation="vertical" >
        <ListView
            android:id="@+id/title_listview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </LinearLayout>

    这个布局也是非常的简单的。

    我们仅仅是是用inflate()成功获取整个布局是不够的,我们还需要获取的ListView,并且给它设置适配器才算是完成任务。

    因为在设置new适配器的时候,第一个参数是Context,所以我们必须获取到TitleFragment所附着的Activity对象,看看回调函数中,发现一个onAttach(Activity activity)这样的函数,可以获取到context对象,因此我们需要在TitleFragment类中声明一个Context的成员属性,并且在onAttach回调函数中把context保存起来,这样在new适配器的时候才有context可以用。

    经过以上的加工,TitleFragment.java的代码如下:

    public class TitleFragment extends Fragment {
        
        private Context context;
        
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) { 
            View v = inflater.inflate(R.layout.title_fragment, container, false);
            ListView listView = (ListView)v.findViewById(R.id.title_listview);
            List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
            
            for (int i = 0; i < MyData.titleArray.length; i++) {
                HashMap<String, String> temp = new HashMap<String, String>();
                temp.put("title", MyData.titleArray[i]);
                list.add(temp);
            }
    
            SimpleAdapter sa = new SimpleAdapter(this.context, list, R.layout.item, new String[]{"title"}, new int[]{R.id.title_textview});
            listView.setAdapter(sa);
            return v;
        }
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            this.context = (MainActivity)activity;
        }
    }

    OK,这样TitleFragment能正确的返回一个带有listView的视图了,我们接着回到MainActivity中去操作。

    操作Fragment必须要有FragmentManager这个对象的,这里有一个坑爹之处。

    官方推荐我们使用的是android.support.v4.app这个包下的Fragment,而不是android.app这个包下的Fragment,因此我们需要用getSupportFragmentManager()去获取android.support.v4.app.FragmentManager

    因此MainActivity需要继承的是FragmentActivity

    接下来的操作就比较简单了,获取FragmentManager,开启事务,替换,提交即可,代码如下:

    public class MainActivity extends FragmentActivity {
        
        private FragmentManager fragmentManager;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            this.fragmentManager = getSupportFragmentManager();
            
            FragmentTransaction ft = this.fragmentManager.beginTransaction();
            TitleFragment titleFragment = new TitleFragment();
            ft.replace(R.id.pager, titleFragment);
            ft.commit();
        }
    }

    OKOK,到目前为止,该程序启动后,会显示出一个列表,木有任何问题,接下来我们要做的,就是点击列表中的一项,可以将整个FrameLayout给换掉,换成详细的页面。那么在ListView那里必须给设置一个监听器,代码如下:

    public class TitleFragment extends Fragment {
        
        private Context context;
        
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) { 
            View v = inflater.inflate(R.layout.title_fragment, container, false);
            ListView listView = (ListView)v.findViewById(R.id.title_listview);
            List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
            
            for (int i = 0; i < MyData.titleArray.length; i++) {
                HashMap<String, String> temp = new HashMap<String, String>();
                temp.put("title", MyData.titleArray[i]);
                list.add(temp);
            }
            
         //设置监听器!!!! listView.setOnItemClickListener(
    new ItemClickListener()); SimpleAdapter sa = new SimpleAdapter(this.context, list, R.layout.item, new String[]{"title"}, new int[]{R.id.title_textview}); listView.setAdapter(sa); return v; } @Override public void onAttach(Activity activity) { super.onAttach(activity); this.context = (MainActivity)activity; }
      //监听器!!!
    class ItemClickListener implements OnItemClickListener { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
            //这里调用的是Activity里面的方法!!! ((MainActivity)TitleFragment.
    this.context).showDetail(arg2); } } }

    因为使用FragmentManager的能力,只有Activity才具备,因此得把替换的方法写在MainActivity里面。MainActivity的代码变成如下的样子

    public class MainActivity extends FragmentActivity {
        
        private FragmentManager fragmentManager;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            this.fragmentManager = getSupportFragmentManager();
            
            FragmentTransaction ft = this.fragmentManager.beginTransaction();
            TitleFragment titleFragment = new TitleFragment();
            ft.replace(R.id.pager, titleFragment);
            ft.commit();
        }public void showDetail(int index) {
         //需要注意的是FragmentTransaction对象commit之后就不能继续使用了,需要重新new一个 FragmentTransaction ft
    = this.fragmentManager.beginTransaction(); DetailFragment detailFragment = new DetailFragment(); Bundle b = new Bundle(); b.putInt("index", index);
         //给detailFragment设置一个参数,这样详细页才能知道自己显示哪一个文章,类似于get请求detail.php?id=112 detailFragment.setArguments(b); ft.replace(R.id.pager, detailFragment);
         //下面这句的作用很大,这句话将该事务加入了回退栈里面,也就是当你显示详细页后,你按后退的按钮,可以回到列表页,如果没有这样做,按后退直接退出了~ ft.addToBackStack(
    "title"); ft.commit(); } }

    注意的要点都在代码的注释,大家看看就懂了,接下来贴下DetailFragment的代码

    public class DetailFragment extends Fragment {
        
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.detail, container, false);
            TextView textView = (TextView)v.findViewById(R.id.content);
         //这里获取到刚刚设置的参数~ Bundle b
    = this.getArguments(); int index = b.getInt("index"); textView.setText(MyData.articleArray[index]); return v; } }

    OKOK,代码基本上贴完了,以上就是在下这两天的学习成果,理解了不少东西,真是很开心,肯定也有些理解不到位的,希望有大神能给与一些指点。哈哈

    原文地址:http://www.cnblogs.com/kross/p/3328389.html

    新浪微博:http://weibo.com/u/1928100503

  • 相关阅读:
    【整理】在一亿个数中寻找出现频率最多的4个
    【整理】静态页面提交数据
    使用SIlverlight 4.0开发时,遇到提示"...Missoft.Silverlight.CSharp.Targets"文件路径不对的解决办法
    关于vs2010服务器资源管理器再添加数据连接时无法获取服务器名的解决办法
    关于Silverlight角色扮演游戏Sprite经典属性设计
    [学习笔记]Silverlight+WCF对数据库进行操作
    【学习】Silverlight中读取XML文件
    TCP/IP之UDP协议
    Tornado Prespective(转)
    TCP/IP之IP选路及动态选路
  • 原文地址:https://www.cnblogs.com/kross/p/3328389.html
Copyright © 2011-2022 走看看