对于Fragment,还必须知道Fragment回退栈以及关键子类,通过本文将学习到Fragment回退栈以及listFragment和DialogFragment的相关知识。
1、管理回退栈
之前提到过Fragment可以当作一个小型的Activity来使用。跟Activity栈一样,fragment也有对应的回退栈,这里要设计到几个关键的API方法,一个是FragmentTransation的addToBackStack()方法将Fragment压入栈,另一个就是FragmentManger里的PopBackStack()将fragment弹出栈。Demo如下:
先上效果:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/fragment_stack_LinearLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/fragment_stack_addbtn" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Add栈" /> <Button android:id="@+id/fragment_stack_popbtn" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Pop栈" /> </LinearLayout> <FrameLayout android:id="@+id/fragment_stack_content_layout" android:layout_below="@id/fragment_stack_LinearLayout" android:layout_margin="10dp" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>布局文件就是一个压栈按钮和一个弹栈按钮,另外还有一个预设放置Fragment的布局。
MainActivity:
package fragment_demo.fragment; import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import com.example.call.R; public class FragmentStackActivity extends Activity { int mStackLevel = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_fragment_stack); // Watch for button clicks. Button button = (Button)findViewById(R.id.fragment_stack_addbtn); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { addFragmentToStack(); } }); button = (Button)findViewById(R.id.fragment_stack_popbtn); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { getFragmentManager().popBackStack(); } }); if (savedInstanceState == null) { //按home键回到桌面后在进入时首先去判断有无状态和参数需要加载 // Do first time initialization -- add initial fragment. Fragment newFragment = CountingFragment.newInstance(mStackLevel); FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.add(R.id.fragment_stack_content_layout, newFragment).commit(); } else { mStackLevel = savedInstanceState.getInt("level"); } } @Override /*保存状态数据。当按手机home键退出后在进入时不会再去绘制Fragment*/ public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("level", mStackLevel); } void addFragmentToStack() { mStackLevel++; // Instantiate a new fragment. Fragment newFragment = CountingFragment.newInstance(mStackLevel); // Add the fragment to the activity, pushing this transaction // on to the back stack. FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.fragment_stack_content_layout, newFragment); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); //动画效果 ft.addToBackStack(null); ft.commit(); } public static class CountingFragment extends Fragment { int mNum; int bgColor[] = new int[]{ android.R.color.holo_green_dark, android.R.color.holo_blue_dark, android.R.color.holo_orange_dark, android.R.color.holo_purple }; /** * Create a new instance of CountingFragment, providing "num" * as an argument. */ static CountingFragment newInstance(int num) { CountingFragment f = new CountingFragment(); // Supply num input as an argument. Bundle args = new Bundle(); args.putInt("num", num); f.setArguments(args); return f; } /** * When creating, retrieve this instance's number from its arguments. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mNum = getArguments() != null ? getArguments().getInt("num") : 1; } /** * The Fragment's UI is just a simple text view showing its * instance number. */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(android.R.layout.simple_list_item_1, container, false); TextView tv = (TextView) v; tv.setText("Fragment #" + mNum); tv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); tv.setGravity(Gravity.CENTER); tv.setBackgroundColor(getActivity().getResources().getColor(bgColor[mNum % 4])); // tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb)); //阴影 return v; } } }
2、关键子类:ListFragment与DialoyFragment
听名字就知道一个是集成了listView和Dialoy对话框的Fragment。下面看Demo怎么来使用这两个子类。
listFragment:在onActivityCreated()里面将适配器和数据源设置给ListFragment即可
package fragment_demo.subfragment; import android.app.Activity; import android.app.Fragment; import android.app.ListFragment; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; /** * A simple {@link Fragment} subclass. */ public class MyListFragment extends ListFragment{ private String[] data = new String[]{"注册", "登录", "退出"}; private ListFragmentAdapter mListAdapter; private MyListFragmentCallBack mCallBack; /*交互接口*/ public interface MyListFragmentCallBack{ public void OnCallBack(String str); } @Override public void onAttach(Activity activity) { super.onAttach(activity); if (activity instanceof MyListFragmentCallBack){ mCallBack = (MyListFragmentCallBack) activity; }else { /*抛没有实现接口的异常*/ new RuntimeException("没有实现接口"); } } public static MyListFragment newInstance() { Bundle args = new Bundle(); MyListFragment fragment = new MyListFragment(); fragment.setArguments(args); return fragment; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mListAdapter = new ListFragmentAdapter(getActivity()); setListAdapter(mListAdapter); mListAdapter.setDataStr(data); } @Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); String str = (String) l.getAdapter().getItem(position); //Toast.makeText(getActivity(),str,Toast.LENGTH_SHORT).show(); mCallBack.OnCallBack(str); } public class ListFragmentAdapter extends BaseAdapter { private String[] dataStr = new String[]{}; private LayoutInflater inflater; public ListFragmentAdapter(Context context) { this.inflater = LayoutInflater.from(context); } public void setDataStr(String[] data) { this.dataStr = data; notifyDataSetChanged(); } @Override public int getCount() { return dataStr.length; } @Override public Object getItem(int i) { return dataStr[i]; } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { if (view == null) { view = inflater.inflate(android.R.layout.simple_list_item_1, null); } TextView txt = (TextView) view; txt.setText((CharSequence) getItem(i)); return view; } } }
DialogFragment:在onCreateDialog()或者是在onCreateView()里面定义好弹出什么样的对话框。
package fragment_demo.subfragment; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.content.DialogInterface; import android.os.Bundle; import android.widget.Toast; /** * Created by scxh on 2015/12/3. */ public class MyDialogFragment extends DialogFragment{ private static final String TAG_PARAM = "param"; private String mParam; public static MyDialogFragment newInstance(String str) { Bundle args = new Bundle(); args.putString(TAG_PARAM,str); MyDialogFragment fragment = new MyDialogFragment(); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null){ mParam = getArguments().getString(TAG_PARAM); } } @Override /*返回弹出的Dialog*/ public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()).setMessage("真的要离开嘛 "+mParam) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { Toast.makeText(getActivity(),"确定",Toast.LENGTH_SHORT).show(); } }).create(); } }
MainActivity:点击listFragment的各个子Item弹出DialogFragment对话框:
package fragment_demo.subfragment; import android.app.Activity; import android.os.Bundle; import com.example.call.R; public class SubFragmentActivity extends Activity implements MyListFragment.MyListFragmentCallBack { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sub_fragment); getFragmentManager().beginTransaction().add(R.id.subfragment_FrameLayout,MyListFragment.newInstance()).commit(); } @Override public void OnCallBack(String str) { MyDialogFragment fragment = MyDialogFragment.newInstance(str); fragment.show(getFragmentManager(),"MyDialogFragment"); } }
效果图: