人生ずっと勉強

人生ずっと勉強ですね。 https://twitter.com/KiyotakaGoto

Android でレイアウト xml に <fragment>タグなど用意せずに fragment を動的に表示させる方法

たとえばあるビューの上ににょきーんと fragment を表示させたいとき、など(この表現で伝わるのか謎ですが・・・)。

基本的な方針

Fragment のクラスに、以下の様な内容のインスタンスメソッドを追加し、アクティビティから適宜呼び出す:
アクティビティとビューを取得し、そのビューをアクティビティに追加する。

Fragment の例

notice メソッドを実行すると、アクティビティのビューの上からにゅいーんとアニメーションして出てくる Fragment の例です。

package com.example.testanimation;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.RelativeLayout;

public class MyFragment extends Fragment {
    public MyFragment() {}
    private TranslateAnimation animation = null;

    @Override
    public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       this.put( "onCreateView" );
       View view = inflater.inflate( R.layout.notice_fragment, container, false );
       return view;
    }

    private TranslateAnimation createAnimation () {
        TranslateAnimation animation = new TranslateAnimation(
                0.0f, 0.0f, -100.0f, 0.0f
        );
        
        animation.setDuration(1000);
        return animation;
    }

    public void notice () {
        Activity activity = this.getActivity();
        View view = this.getView();

        if ( this.animation == null ) {
            this.animation = this.createAnimation();

            RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                    LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT
            );
            
            activity.addContentView(view, layoutParams );
        }
        
        view.startAnimation( this.animation );
    }
}

res/layout/notice_fragment.xml :

<RelativeLayout 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:background="@android:color/holo_blue_light"
    tools:context=".MainActivity" >

    <ImageView
        android:id="@+id/Icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/noticeMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/Icon"
        android:layout_alignTop="@+id/Icon"
        android:text="message1." />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/Icon"
        android:layout_alignBottom="@+id/Icon"
        android:text="message2." />

    <ImageView
        android:id="@+id/SmallIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/noticeMessage"
        android:layout_alignTop="@+id/noticeMessage"
        android:src="@drawable/ic_launcher" />
    
</RelativeLayout>

FragmentActivity の例

package com.example.testanimation;

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

public class MainActivity extends FragmentActivity {
    
    private static final String NOTICE_FRAGMENT_TAG = "notice_fragment_tag";
    private MyFragment myFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        if ( savedInstanceState != null ) {
            this.myFragment = (MyFragment) this.getSupportFragmentManager().findFragmentByTag( MainActivity.NOTICE_FRAGMENT_TAG );
        }
        else {
            this.myFragment = new MyFragment();
            this.getSupportFragmentManager().beginTransaction().add( this.myFragment, MainActivity.NOTICE_FRAGMENT_TAG).commit();
        }
        setContentView(R.layout.activity_main);
        
        Button noticeButton = (Button) this.findViewById( R.id.startButton );
        noticeButton.setOnClickListener( new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // ボタンを押したらフラグメントの notice メソッドを呼び出すことで、にょいーんと出てくる。
                MainActivity.this.myFragment.notice();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

activity_main.xml :

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <Button
        android:id="@+id/startButton"
        android:layout_below="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="start"
        />
</RelativeLayout>

※まだ Android 開発に慣れていないので、まずいコードがあるかもしれません。