[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されて表示されます。