Android学习之路-fragment之三

对于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;
        }
    }
}

Activity里面定义了一个内部类Fragment,在点击按钮是调用 ft.addToBackStack( null )方法将Fragment压入回退栈(在提交事务comit()方法之前),点击弹栈按钮时调用 getFragmentManager().popBackStack();将当前fragment弹出回退栈并显示栈顶的fragment内容。

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");
    }
}

效果图:






你可能感兴趣的:(DialogFragment,Fragment回退栈,ListFragment使用)