My blog

Add intelligent tagline here

[Android]Android Compatibility packageを使って、Fragmentsを1.6上で動かす

Honeycomb(3.0)から使えるというFragmentsですが、これを1.6以上でも使えるようにするstatic libraryが公開されました。 http://android-developers.blogspot.com/2011/03/fragments-for-all.html

ぼくが持っているのはあのIS01で、(いろいろしない限り)1.6しか動きません。というわけで、このライブラリを早速使ってみることにしました。

libraryのインストール

  • SDKのUpdate マネージャからダウンロードします。”Android Compatibility package, revision 1” です。
  • extras/android/compatibility/v4/android-support-v4.jar をbuild pathに追加します。
  • android.support.v4.app.* をimportします

これで使えるようになります。import元が3.0とは異なるのがちょっといやですね。

Fragment

Activity.getFragmentManager()はありませんが、代わりにFragmentActivity.getSupportFragmentManager()が定義されています。なお、Fragment.getFragmentManager()はNULLが返ってくるようです。

サンプル

こちら に掲載されているサンプルを1.6でも動くように手直しました。

ちなみに、1.6で動かすために以下の点にひっかかりました。 * match_parentはAPI Level 8から導入 * ListViewのidに制限

ちなみに、addToBackStackを呼んでいるので、ボタンを押すたびにFragmentがBackStackに積まれます。

Main.java

package com.example.test.fragment;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.support.v4.app.*;

import com.example.test.fragment.R;

public class Main extends FragmentActivity{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        for(int i = 1;i < 6;i++){
            int resId = getResources().getIdentifier("button" + i, "id", getPackageName());
            setCallback((Button)findViewById(resId), i);
        }
    }
    private void setCallback(Button b, final int i){
     b.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
                     stackAFragment(i);
             }
     });
    }
    private void stackAFragment(int nAndroids) {
        Fragment f = new LogoFragment(nAndroids);

        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.the_frag, f);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.addToBackStack(null);
        ft.commit();
    }
}

LogoFragment.java

package com.example.test.fragment;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.support.v4.app.*;

public class LogoFragment extends Fragment {
    private int nAndroids = 1;

    public LogoFragment(){
    }
    public LogoFragment(int nAndroids) {
        this.nAndroids = nAndroids;
    }
    @Override
    public void onCreate(Bundle saved) {
        super.onCreate(saved);
        if (null != saved) {
                nAndroids = saved.getInt("nAndroids");
        }
    }

    @Override
    public void onSaveInstanceState(Bundle toSave) {
        toSave.putInt("nAndroids", nAndroids);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saved) {
        Context c = getActivity().getApplicationContext();
        LinearLayout l = new LinearLayout(c);
        for (int n = 0; n < nAndroids; n++) {
                ImageView i = new ImageView(c);
                i.setImageResource(R.drawable.icon);
                l.addView(i);
        }
        return l;
    }
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    andro`id:orientation <http://d.hatena.ne.jp/orientation/>`_="horizontal"
    andro`id:layout_height <http://d.hatena.ne.jp/layout_height/>`_="fill_parent"
    andro`id:id <http://d.hatena.ne.jp/id/>`_="@+id/frags" andro`id:layout_width <http://d.hatena.ne.jp/layout_width/>`_="fill_parent">
    <LinearLayout andro`id:layout_height <http://d.hatena.ne.jp/layout_height/>`_="fill_parent" andro`id:id <http://d.hatena.ne.jp/id/>`_="@+id/linearLayout1" andro`id:layout_width <http://d.hatena.ne.jp/layout_width/>`_="wrap_content" andro`id:orientation <http://d.hatena.ne.jp/orientation/>`_="vertical">
        <Button andro`id:text <http://d.hatena.ne.jp/text/>`_="Button" andro`id:id <http://d.hatena.ne.jp/id/>`_="@+id/button1" andro`id:layout_width <http://d.hatena.ne.jp/layout_width/>`_="wrap_content" andro`id:layout_height <http://d.hatena.ne.jp/layout_height/>`_="wrap_content"></Button>
        <Button andro`id:text <http://d.hatena.ne.jp/text/>`_="Button" andro`id:id <http://d.hatena.ne.jp/id/>`_="@+id/button2" andro`id:layout_width <http://d.hatena.ne.jp/layout_width/>`_="wrap_content" andro`id:layout_height <http://d.hatena.ne.jp/layout_height/>`_="wrap_content"></Button>
        <Button andro`id:text <http://d.hatena.ne.jp/text/>`_="Button" andro`id:id <http://d.hatena.ne.jp/id/>`_="@+id/button3" andro`id:layout_width <http://d.hatena.ne.jp/layout_width/>`_="wrap_content" andro`id:layout_height <http://d.hatena.ne.jp/layout_height/>`_="wrap_content"></Button>
        <Button andro`id:text <http://d.hatena.ne.jp/text/>`_="Button" andro`id:id <http://d.hatena.ne.jp/id/>`_="@+id/button4" andro`id:layout_width <http://d.hatena.ne.jp/layout_width/>`_="wrap_content" andro`id:layout_height <http://d.hatena.ne.jp/layout_height/>`_="wrap_content"></Button>
        <Button andro`id:text <http://d.hatena.ne.jp/text/>`_="Button" andro`id:id <http://d.hatena.ne.jp/id/>`_="@+id/button5" andro`id:layout_width <http://d.hatena.ne.jp/layout_width/>`_="wrap_content" andro`id:layout_height <http://d.hatena.ne.jp/layout_height/>`_="wrap_content"></Button>
    </LinearLayout>

    <fragment class="com.example.test.fragment.LogoFragment"
            andro`id:id <http://d.hatena.ne.jp/id/>`_="@+id/the_frag"
            andro`id:layout_width <http://d.hatena.ne.jp/layout_width/>`_="fill_parent"
            andro`id:layout_height <http://d.hatena.ne.jp/layout_height/>`_="fill_parent" />
</LinearLayout>

Fragment豆知識

removeとかreplaceしたときメモリはどうなるの?

addToBackStack()を呼んでいると、BackStackに積まれます。呼んでいないとメモリから破棄されます。つまり、onDetach()までが呼ばれます。

BackStackに積まれているときにBackボタンを押したらどうなるの?

その時表示されているFragmentは破棄され(onDetachまで呼ばれる)、BackStackの一番上にあるFragmentがpopされて表示されます。