import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; public class HotspotScanDialog extends DialogFragment { SetupHotspotDialogListener mListener; @Override public Dialog onCreateDialog(Bundle savedInstanceState) { ... .setAdapter(hotspotAdapter,new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog,int which) { mListener.onHotspotSelectedListener(hotspotAdapter.getItem( which).toString()); } })... } public interface SetupHotspotDialogListener { public void onHotspotSelectedListener(String selection); } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (SetupHotspotDialogListener) activity; } catch (ClassCastException ignore) { // Just to make sure if anyone will be pointing at my throwing // ClassCastException myself I have tried without this code as well. throw new ClassCastException(activity.toString() + " must implement NoticeDialogListener"); } } }
这是我的Fragment使用上面的DialogFragment:
import android.app.AlertDialog; import android.app.DialogFragment; import android.support.v4.app.Fragment; import com.xxx.yyy.ui.compontent.dialog.HotspotScanDialog; import com.xxx.yyy.ui.compontent.dialog.HotspotScanDialog.SetupHotspotDialogListener; public class SmartMode extends Fragment implements SetupHotspotDialogListener { private void showWifiSelectionDialog() { DialogFragment setupWifiSelectionDialog = new HotspotScanDialog(); /* * using getFragmentManager() only says "The method * show(FragmentManager,String) in the type DialogFragment is not * applicable for the arguments (FragmentManager,String)" */ setupWifiSelectionDialog.show(getActivity().getFragmentManager(),Keys.TAG.toString()); } @Override public void onHotspotSelectedListener(String selection) { // Log.d(TAG,selection); } }
这是错误日志:
02-01 13:11:32.750: E/AndroidRuntime(15061): FATAL EXCEPTION: main
02-01 13:11:32.750: E/AndroidRuntime(15061): java.lang.ClassCastException: com.milanix.tuki.UiMainActivity@41d75350 must implement NoticeDialogListener
02-01 13:11:32.750: E/AndroidRuntime(15061): at com.xxx.yyy.ui.compontent.dialog.HotspotScanDialog.onAttach(HotspotScanDialog.java:122)
02-01 13:11:32.750: E/AndroidRuntime(15061): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:787)
02-01 13:11:32.750: E/AndroidRuntime(15061): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035)
02-01 13:11:32.750: E/AndroidRuntime(15061): at android.app.BackStackRecord.run(BackStackRecord.java:635)
02-01 13:11:32.750: E/AndroidRuntime(15061): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1397)
02-01 13:11:32.750: E/AndroidRuntime(15061): at android.app.FragmentManagerImpl$1.run(FragmentManager.java:426)
02-01 13:11:32.750: E/AndroidRuntime(15061): at android.os.Handler.handleCallback(Handler.java:615)
02-01 13:11:32.750: E/AndroidRuntime(15061): at android.os.Handler.dispatchMessage(Handler.java:92)
02-01 13:11:32.750: E/AndroidRuntime(15061): at android.os.Looper.loop(Looper.java:137)
02-01 13:11:32.750: E/AndroidRuntime(15061): at android.app.ActivityThread.main(ActivityThread.java:4898)
02-01 13:11:32.750: E/AndroidRuntime(15061): at java.lang.reflect.Method.invokeNative(Native Method)
02-01 13:11:32.750: E/AndroidRuntime(15061): at java.lang.reflect.Method.invoke(Method.java:511)
02-01 13:11:32.750: E/AndroidRuntime(15061): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
02-01 13:11:32.750: E/AndroidRuntime(15061): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
02-01 13:11:32.750: E/AndroidRuntime(15061): at dalvik.system.NativeStart.main(Native Method)
我想知道是否有人可以暗示这个问题.
解决方法
onAttach(Activity) called once the fragment is associated with its activity.
在你的代码中
mListener = (SetupHotspotDialogListener) activity;
line抛出ClassCastException,因为您的活动未实现SetupHotspotDialogListener接口. (片段直接与包含它的活动相关联,以及DialogFragment,因为DialogFragment扩展了Fragment).
从docs开始
在某些情况下,您可能需要一个片段来与活动共享事件.一种好方法是在片段内定义一个回调接口,并要求主机活动实现它.当活动通过接口收到回调时,它可以根据需要与布局中的其他片段共享信息.
所以如果你想从Fragment创建FragmentDialog我建议通过回调来组织它到活动:
>使用createDialogRequest()等方法在SmartMode Fragment类中创建回调接口(就像在dialogFragment中一样).
>让您的活动实现该界面
>然后,当您需要创建对话框时,将回调从Fragment发送到Activity
>将“show dialog logics”放入Activity
它看起来像片段询问活动来创建对话框,活动显示对话框.
编辑:
我想我已经找到了更好的实现你需要的东西.我写了一个简单的例子,从片段创建片段对话框,接收片段对话框回调事件到片段.
活动:
public class MyFragmentActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_fragment); // first start of activity if (savedInstanceState == null) { // put fragment to activity layout MyFragment fragment = new MyFragment(); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.fragmentContainer,fragment,"fragment"); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); ft.commit(); } }}
分段:
public class MyFragment extends Fragment implements MyDialogInterface { @Override public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) { super.onCreateView(inflater,container,savedInstanceState); View fragmentView = inflater.inflate(R.layout.fragment,null); // button which shows dialog Button showDialogButton = (Button) fragmentView.findViewById(R.id.showDialog); showDialogButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // create fragment dialog. FragmentDialog dialog = FragmentDialog.getInstance(MyFragment.this); dialog.show(getActivity().getSupportFragmentManager(),"dialog"); } }); return fragmentView; } @Override public void onClickEvent() { // receive click events from dialog fragment Log.e(getClass().getSimpleName(),"onClickEvent"); }
}
FragmentDialog:
public class FragmentDialog extends DialogFragment { public interface MyDialogInterface extends Serializable { public void onClickEvent(); } private MyDialogInterface callbackListener; /** * dialogInterface - instance of MyDialogInterface which will handle * callback events */ public static FragmentDialog getInstance(MyDialogInterface dialogInterface) { FragmentDialog fragmentDialog = new FragmentDialog(); // set fragment arguments Bundle args = new Bundle(); args.putSerializable("dialogInterface",dialogInterface); fragmentDialog.setArguments(args); return fragmentDialog; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setStyle(STYLE_NO_TITLE,0); } @Override public View onCreateView(LayoutInflater inflater,Bundle savedInstanceState) { View pushDialogView = getActivity().getLayoutInflater().inflate(R.layout.fragment_dialog,null); // get reference to MyDialogInterface instance from arguments callbackListener = (MyDialogInterface) getArguments().getSerializable("dialogInterface"); Button cancelButton = (Button) pushDialogView.findViewById(R.id.button); cancelButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // send click event callbackListener.onClickEvent(); } }); return pushDialogView; }}
我使用了支持4个库片段(android.support.v4.app.Fragment,android.support.v4.app.DialogFragment,android.support.v4.app.FragmentActivity).
和布局:
activity_my_fragment.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragmentContainer" android:layout_width="match_parent" android:layout_height="match_parent" />
fragment.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#a00" android:orientation="vertical" > <Button android:id="@+id/showDialog" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="show doalog" /> </LinearLayout>
fragment_dialog.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#fe3" android:orientation="vertical" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="click me" /> </LinearLayout>
我的想法是发送引用接口,它将捕获回调事件.