Fragment.onAttachは、FragmentがActivityにアタッチされた時に呼ばれる。
Fragment | Android Developers
アタッチって表現が難しい(紐付けられると言えばそう)のだが、ここに来ると、Activityを参照できるようになるらしい。
それはさておいて、Activityへのコールバックについて試してみる。
strings.xmlで、
Fragmentを2つ使うので、ButtonもTextViewもそれぞれに。
activity_main.xmlは、
FrameLayoutを中に。
fragment1_main.xmlは、
TextViewとButton。
fragment2_main.xmlも、
同じ。
CustomListener.javaを追加し、
package com.bgstation0.android.sample.fragment_;
public interface CustomListener {
void onButtonClicked();
}
ボタンを押された時の独自コールバック。
Fragment1.javaで、
package com.bgstation0.android.sample.fragment_;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
public class Fragment1 extends Fragment {
static final String TAG = "Fragment1";
private CustomListener mCustomListener = null;
public Fragment1(){
}
public static Fragment1 newInstance(){
Fragment1 fragment1 = new Fragment1();
return fragment1;
}
public void setCustomListener(CustomListener listener){
mCustomListener = listener;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment1_main, null);
Button button = (Button)view.findViewById(R.id.fragment1_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TODO
mCustomListener.onButtonClicked();
}
});
return view;
}
}
setCustomListenerで渡されたコールバックをセット。
Buttonが押されたら、実行。
Fragment2.javaも、
package com.bgstation0.android.sample.fragment_;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
public class Fragment2 extends Fragment {
static final String TAG = "Fragment2";
private CustomListener mCustomListener = null;
public Fragment2(){
}
public static Fragment2 newInstance(){
Fragment2 fragment2 = new Fragment2();
return fragment2;
}
public void setCustomListener(CustomListener listener){
mCustomListener = listener;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment2_main, null);
Button button = (Button)view.findViewById(R.id.fragment2_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TODO
mCustomListener.onButtonClicked();
}
});
return view;
}
}
同じ。
MainActivity.javaは、
package com.bgstation0.android.sample.fragment_;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
public class MainActivity extends Activity {
static final String TAG = "MainActivity";
Context mContext = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
if (savedInstanceState == null){
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment1 fragment1 = Fragment1.newInstance();
fragment1.setCustomListener(new CustomListener(){
@Override
public void onButtonClicked(){
Toast.makeText(mContext, TAG + " Callback", Toast.LENGTH_LONG).show();
}
});
fragmentTransaction.replace(R.id.framelayout1, fragment1);
fragmentTransaction.commit();
}
}
}
fragment1.setCustomListenerの引数で、CustomListenerを定義してる。
Buttonが押されたらToast表示。
このFragmentを置換。
起動時。
Button押すと、
Toast表示。
回転して、Buttonを押すと、
おや?
落ちる。
回転するとコールバックのセットが無いから。
そこで、
package com.bgstation0.android.sample.fragment_;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
public class MainActivity extends Activity implements CustomListener{
static final String TAG = "MainActivity";
Context mContext = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
if (savedInstanceState == null){
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment1 fragment1 = Fragment1.newInstance();
fragmentTransaction.replace(R.id.framelayout1, fragment1);
fragmentTransaction.commit();
}
}
@Override
public void onButtonClicked(){
Toast.makeText(mContext, TAG + " Callback", Toast.LENGTH_LONG).show();
}
}
MainActivity.javaで、CustomListenerのonButtonClickedを実装してしまう。
package com.bgstation0.android.sample.fragment_;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
public class Fragment1 extends Fragment {
static final String TAG = "Fragment1";
public Fragment1(){
}
public static Fragment1 newInstance(){
Fragment1 fragment1 = new Fragment1();
return fragment1;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment1_main, null);
Button button = (Button)view.findViewById(R.id.fragment1_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TODO
((MainActivity)getActivity()).onButtonClicked();
}
});
return view;
}
}
getActivityで取得したActivityをMainActivityにキャストして、onButtonClickedを呼べば、コールバック呼べてしまう。
setCustomListenerもいらないし。
package com.bgstation0.android.sample.fragment_;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
public class Fragment1 extends Fragment {
static final String TAG = "Fragment1";
private CustomListener mCustomListener = null;
public Fragment1(){
}
public static Fragment1 newInstance(){
Fragment1 fragment1 = new Fragment1();
return fragment1;
}
@Override
public void onAttach(Activity activity){
super.onAttach(activity);
mCustomListener = (CustomListener)activity;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment1_main, null);
Button button = (Button)view.findViewById(R.id.fragment1_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TODO
mCustomListener.onButtonClicked();
}
});
return view;
}
}
onArrachでActivityが渡されるので、それをmCustomListenerに保持しておいてもいい。
ここにonAttachの使いどころがある。
回転前もToastが出る。
回転後も落ちずにToast出る。
これで、コールバックはできたけど、最後にFragmentの中からActivityに飛んで、ActivityからFragmentの存在に関わる処理をしても、問題ないか試す。
CustomListener.javaで、
intの引数noをもらう。
Fragment1.javaで、
mCustomListener.onButtonClickedで1を渡す。
Fragment2.javaでは、
2を渡す。
MainActivity.javaでは、
1の時は2に置換、2の時は1を置換。
Buttonを押したら、別の片方に切り替わるということ。
Button1を押すと、
Fragment2に切り替わる。
横にしてButton2を押すと、
Fragment1に戻る。
このような切り替えができるので、ActivityからFragmentの存在に関わる処理が出来る。
Sample/android/Fragment/onAttach/src/Fragment at master · bg1bgst333/Sample · GitHub