如何使用Fragment建立TabActivity之二

如何使用Fragment建立TabActivity之二

又被google丟掉了, 如果想要換成新版的TabHost請參考
如何使用Toolbar+DrawerLayout+Tab+SwipRefresh
或者我之後再獨立一篇出來


還沒講完…先別急著走。
在如何使用Fragment建立TabActivity裡面, 我們好像漏掉很重要的東西?
沒錯, 就是切換的Fragment咧??
現在繼續討論怎麼把每一個Fragment加到對應的分頁!

在官網提到, Fragment可以用五個模式分別是:

FragmentManager
FragmentTransaction
Fragment
ListFragment
DialogFragment

前兩個在上一篇用過了, 接著後面三個呢?
第三個有點似曾相似, 它就是我們在子分頁當中所繼承的東西!
另外剩下的兩個是Android幫我建立好的東西, 就一口氣講這三種吧!

回到上一篇的範例, 我們只需要變動Fragment1~Fragment4這四個類別就好了。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <ListView  
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent"
        android:id="@+id/listView"
    />
</LinearLayout>

首先先用最原始的方式來取得ListView, 在一個LinearLayout之下放一個ListView,
並且設定一個id。

public class Fragment1 extends Fragment {
    private ListView listView;
    private View v;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        v = inflater.inflate(R.layout.fragment1_list, container, false);
        listView = (ListView)v.findViewById(R.id.listView);
        String[] arr = new String[]{
             "A","B","C","D","E","F","G"
        };
        ArrayAdapter<String> adapter = 
            new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_1,arr);
        listView.setAdapter(adapter);
        return v;
    }
}

一開始必須覆寫兩個方法, 一個是onCreateView以及onCreate,
首先在onCreateView裡面, 將你的Layout讀進去, 接下來將listview作一些設定,
就像一般在使用listview一樣, 可以使用SimpleAdapter或者自訂的Adapter來設定listview的樣式,
在這個例子是利用最簡單的ArrayAdapter, 接著設定好了以後, 將v回傳回去,
你就可以看到這樣的畫面。

如果要加入事件, 跟一般ListView加入事件是相同的!

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    v = inflater.inflate(R.layout.fragment1_list, container, false);
    listView = (ListView)v.findViewById(R.id.listView);
    final String[] arr = new String[]{
       "A","B","C","D","E","F","G"
    };
    ArrayAdapter<String> adapter = 
        new ArrayAdapter<String>(getActivity(),
        android.R.layout.simple_list_item_1,arr);
    listView.setAdapter(adapter);
    listView.setOnItemClickListener(new OnItemClickListener(){

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
            // TODO Auto-generated method stub
            Toast.makeText(getActivity(), "你按下"+arr[position], Toast.LENGTH_SHORT).show();
        }

    });
    return v;
}

那你就會看到這樣的畫面!

那如果懶得自己取得ListView來塞東西呢?
很簡單! Android又幫你做好了, 由於ListView實在是太常用到了,
因此Android直接幫你把ListView綁上去, 有沒有很熟悉, 像一般ListView如果綁住Activity,
那麼我們可以直接繼承ListViewActivity,
同理, 我們也可以直接繼承ListViewFagment。

先寫一個fragment2_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <ListView  
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent"
        android:id="@id/android:list"
    />
</LinearLayout>

咦? 跟上一個fragment1_list.xml有什麼不同?
仔細看! id不一樣了! 變成android內建好的id了。

再來就是佈置我們的Fragment2類別了。

public class Fragment2 extends ListFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        String[] arr = new String[]{
           "H","I","J","K","L","M","N"
        };
        ArrayAdapter<String> adapter 
           = new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_1,arr);
        setListAdapter(adapter);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        return inflater.inflate(R.layout.fragment2_list, container, false);
    }
}

我們發現只要直接在onCreateView套入fragment2_list.xml,
就可以直接設定adapter到這個Fragment,
程式碼好像也少了許多, 還不賴的感覺。

挖嗚, 原來可以這麼簡單。
那來加個觸發事件好了, 只要覆寫onListItemClick即可。

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    // TODO Auto-generated method stub
    super.onListItemClick(l, v, position, id);
    Toast.makeText(getActivity(), "你按下"+arr[position], Toast.LENGTH_SHORT).show();
}

程式碼簡單了許多。

都是ListView有點單調, 第三個Fragment來加入GridView好了。
可以參考一下 如何使用GridView,
我們照著這篇教學進行, 一開始先下載教學檔案內的圖檔,

先將fragment_gridview.xml設定好

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <GridView  
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
        android:id="@+id/main_page_gridview"
        android:numColumns="auto_fit"
        android:gravity="center"
        android:columnWidth="50pt"
        android:stretchMode="columnWidth"
    />
</LinearLayout>

接著先宣告好資源檔案。

private GridView gridView;
private int[] image = {
    R.drawable.cat, R.drawable.flower, R.drawable.hippo,
    R.drawable.monkey, R.drawable.mushroom, R.drawable.panda,
    R.drawable.rabbit, R.drawable.raccoon
};
private String[] imgText = {
    "cat", "flower", "hippo", "monkey", "mushroom", "panda", "rabbit", "raccoon"
};

然後在新增一個grid_item.xml, 用來裝gridview的樣子。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    >
    <ImageView android:id="@+id/image"
        android:layout_width="35pt"
        android:layout_height="35pt"
        android:layout_marginTop="5pt"
        >
    </ImageView>

    <TextView 
        android:layout_height="fill_parent"
        android:layout_width="fill_parent"
        android:id="@+id/text"
        android:textSize="9pt"
        android:gravity="center"
        android:paddingTop = "15px"
        android:paddingBottom = "15px">
    </TextView>
</LinearLayout>

然後再onCreateView新增下面的程式碼

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    View v = inflater.inflate(R.layout.fragment3_gridview, container, false);
    List<Map<String, Object>> items = new ArrayList<Map<String,Object>>();
    for (int i = 0; i < image.length; i++) {
        Map<String, Object> item = new HashMap<String, Object>();
        item.put("image", image[i]);
        item.put("text", imgText[i]);
        items.add(item);
    }
    SimpleAdapter adapter = new SimpleAdapter(getActivity(), 
        items, R.layout.grid_item, new String[]{"image", "text"},
        new int[]{R.id.image, R.id.text});

    gridView = (GridView)v.findViewById(R.id.main_page_gridview);
    gridView.setNumColumns(3);
    gridView.setAdapter(adapter);
    gridView.setOnItemClickListener(new OnItemClickListener(){
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Toast.makeText(getActivity(), "你按下 "+imgText[position],    
                Toast.LENGTH_SHORT).show();   
        }

    });
    return v;
}

基本上沒變動多大, 跟fragment1.java一樣, 把gridview拿到onCreateView來用而已。

連事件都加上了。
最後一個類別來一個比較複雜的元件, Gallery好了。
可以參考如何使用Gallery跟ImageSwitcher, 相同概念,
全部都塞進onCreateView來進行初始化。

宣告好fragment4_gallery.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ImageSwitcher android:id="@+id/image_switcher"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1"
    />

    <Gallery android:id="@+id/gallery"
        android:background="#55000000"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"        
        android:gravity="center_vertical"
        android:spacing="1dp"
        android:layout_weight="0"
    />
</LinearLayout>

然後宣告gallery_switcher.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <ImageView
     android:layout_width="wrap_content"
     android:layout_height="100px"
        android:id="@+id/image"
        android:layout_gravity="center"
    />
    <TextView
  android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/text" 
        android:textSize="30px"
        android:layout_gravity="center"
        android:textColor="#ffffff"
        />
</LinearLayout>

宣告好所有的圖檔

private int[] image = {
    R.drawable.cat, R.drawable.flower, R.drawable.hippo,
    R.drawable.monkey, R.drawable.mushroom, R.drawable.panda,
    R.drawable.rabbit, R.drawable.raccoon
};
private String[] imgText = {
    "cat", "flower", "hippo", "monkey", "mushroom", "panda", "rabbit", "raccoon"
};
private Gallery gallery;
private ImageSwitcher imageSwitcher;
private SimpleAdapter simpleAdapter;

接著照著上面的步驟跑onCreateView的時候, 將畫面以及事件建構完成。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    View v = inflater.inflate(R.layout.fragment4_gallery, container, false);
    imageSwitcher = (ImageSwitcher)v.findViewById(R.id.image_switcher);
    gallery = (Gallery)v.findViewById(R.id.gallery);
    List<Map<String, Object>> items = new ArrayList<Map<String,Object>>();
    for (int i = 0; i < image.length; i++) {
        Map<String, Object> item = new HashMap<String, Object>();
        item.put("image", image[i]);
        item.put("text", imgText[i]);
        items.add(item);
    }
    simpleAdapter = new SimpleAdapter(getActivity(), 
        items, R.layout.gallery_switcher, new String[]{"image", "text"},
        new int[]{R.id.image, R.id.text});

    gallery.setAdapter(simpleAdapter);

    imageSwitcher.setFactory(new ViewFactory(){

        @Override
        public View makeView() {
            ImageView imageView = new ImageView(getActivity());
            imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
            imageView.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.FILL_PARENT, 180));
            return imageView;
        }

    });
    imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.slide_in_left));
    imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.slide_out_right));
    gallery.setOnItemClickListener(new OnItemClickListener(){

        @Override
        public void onItemClick(AdapterView<?> parent, View arg1, int position,
            long id) {
            imageSwitcher.setImageResource(image[position]);
        }
    });
    return v;
}

這樣一來就可以看到以下的畫面。

這樣就完成四個子介面了。

程式碼

相關教學
如何使用Fragment建立TabActivity之一
如何使用Fragment建立TabActivity之三