Android Fragment详解(3)->横竖屏幕切换完整示例

Android Fragment详解(三)---横竖屏幕切换完整示例MainActivity如下:package cc.testsimplefragment2imp

Android Fragment详解(三)--->横竖屏幕切换完整示例

MainActivity如下:

package cc.testsimplefragment2;import android.app.Activity;import android.os.Bundle;/** * Demo描述: * Fragment使用示例 *  * 备注说明: * 1 在main.xml中存在一个Fragment即 *   TitleListFragment.用它来显示Titles * 2 点击TitleListFragment中的某个条目的时候 *   判断的横竖屏 *   2.1 若是横屏,则用另外一个Fragment显示详细信息 *   2.2 若是竖屏,则启动另一个Activity显示详细信息 *       2.2.1 在该Activity中动态添加一个Fragment显示详细信息 *  * 参考文档: * 1 http://blog.csdn.net/t12x3456/article/details/8120309 * 2 http://blog.csdn.net/nkmnkm/article/category/958669/5 * 3 http://blog.csdn.net/xiaanming/article/details/9254749 *   Thank you very much * */public class MainActivity extends Activity {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main); }@Overrideprotected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);System.out.println("---> MainActivity onSaveInstanceState()");}}


TitleListFragment如下:

package cc.testsimplefragment2;import android.app.FragmentTransaction;import android.app.ListFragment;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.ArrayAdapter;import android.widget.ListView;public class TitleListFragment extends ListFragment {//当前是否为横屏private boolean currentIsLand;//当前选中位置private int currentCheckedPosition = -1; private final String currentCheckedKey="currentChecked";//每次重绘Fragment时都会调用该onActivityCreated()方法@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);        System.out.println("---> onActivityCreated");//设置适配器ArrayAdapter<String> arrayAdapter=new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_checked, Data.TITLES);setListAdapter(arrayAdapter); //判断当前是否为横屏//注意方式://先利用getActivity()找到该Fragment隶属于的Activity,再findViewById()//为什么要这么判断是否是横屏呢?//因为横屏的时候会去读取layout-land下的main.xml布局文件//在该布局文件下有一个RelativeLayout,其id为containerRelativeLayout//所以,若能找到它那么就可以表明当前是横屏View containerView = getActivity().findViewById(R.id.containerRelativeLayout);currentIsLand = containerView != null && containerView.getVisibility() == View.VISIBLE; if (savedInstanceState != null) {currentCheckedPosition = savedInstanceState.getInt(currentCheckedKey, 0);getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); getListView().setItemChecked(currentCheckedPosition, true); System.out.println("---> onActivityCreated() currentCheckedPosition="+currentCheckedPosition);}else{System.out.println("---> onActivityCreated() savedInstanceState == null ");}if (currentIsLand) { //设置ListView为单选模式getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); showDetailContent(currentCheckedPosition); }}@Overridepublic void onStart() {super.onStart();System.out.println("---> onStart");}//处理手机一直在竖屏时://点击标题,跳转后,再按下back键的情况@Overridepublic void onResume() {super.onResume();System.out.println("---> onResume");if (!currentIsLand) {getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);//currentCheckedPosition默认为-1//所以在第一次时不选择任何一个if (currentCheckedPosition>=0) {getListView().setItemChecked(currentCheckedPosition, true);}}}//保存数据//Fragment被系统或者某些内存清理,或者横竖屏切换而被销毁时//将会触发onSaveInstanceState(Bundle savedInstanceState)://Called to ask the fragment to save its current dynamic state,//so it can later be reconstructed in a new instance of its process is restarted.//然后调用onActivityCreated()生命周期方法,重绘Fragment    //存在的疑问://在手机一直竖屏的情况下,点击TitleListFragment的条目//为什么会执行该onSaveInstanceState()方法和MainActivity的//onSaveInstanceState()方法@Overridepublic void onSaveInstanceState(Bundle bundle) {super.onSaveInstanceState(bundle);bundle.putInt(currentCheckedKey, currentCheckedPosition);System.out.println("---> onSaveInstanceState()");System.out.println("---> onSaveInstanceState() currentCheckedPosition="+currentCheckedPosition);}//点击ListFragment上的某个条目时调用@Overridepublic void onListItemClick(ListView l, View v, int position, long id) {showDetailContent(position); }//显示详细内容private void showDetailContent(int index) {//保存当前被选中的位置currentCheckedPosition=index;//横屏时if (currentIsLand) {//1  先设置TitleListFragment//  改变ListFragment的index位置被选中getListView().setItemChecked(index, true); //2  再设置DetailFragment//  利用FragmentManager判断在某个容器(container)中是否有一个DetailFragment//  如果没有或在有的情况下其CheckedIndex不等于当前被选中的index//  则进行replace()操作DetailFragment detailFragment = (DetailFragment) getFragmentManager().findFragmentById(R.id.containerRelativeLayout); if (detailFragment == null || detailFragment.getCheckedIndex() != index) {//生成新的Fragment.detailFragment = DetailFragment.newInstance(index);//开始Fragment的事务Transaction//因为在这个事务中执行了replace()操作,所以会将该//detailFragment attach到activity,按照生命周期//的顺序必然会调用DetailFragment的onCreateView().//更加白话地说:其实相当于我们先做了一些内在的东西,再做了外在的东西.//什么意思呢?//内在的部分:我们先new了一个DetailFragment,并且为这个DetailFragment//设置了一些参数.//这些都体现在了DetailFragment.newInstance(index)方法中//外在的部分:利用replace()将该DetailFragment attach到activity//这些都体现在了DetailFragment的onCreateView()方法中.所以在//该方法中我们可以去取为此DetailFragment设置的参数.//即方法getCheckedIndex()FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();//替换容器(container)原来的FragmentfragmentTransaction.replace(R.id.containerRelativeLayout, detailFragment); //设置转换效果fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); //提交事务fragmentTransaction.commit(); }        //竖屏时} else { Intent intent = new Intent(getActivity(),DetailActivity.class);intent.putExtra("index", index); startActivity(intent); }}}


DetailFragment如下:

package cc.testsimplefragment2;import android.app.Fragment;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ScrollView;import android.widget.TextView;public class DetailFragment extends Fragment {//往ScrollView中添加一个TextView然后将其返回@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {if (container == null) {return null;}ScrollView scrollView = new ScrollView(getActivity()); TextView textView = new TextView(getActivity()); textView.setPadding(10, 10, 10, 10); scrollView.addView(textView); textView.setText(Data.DETAILS[getCheckedIndex()]); return scrollView;}//生成DetailFragment实例,并且保存indexpublic static DetailFragment newInstance(int index) {DetailFragment detailFragment = new DetailFragment();Bundle bundle = new Bundle(); bundle.putInt("index", index); detailFragment.setArguments(bundle);return detailFragment;}//取出indexpublic int getCheckedIndex() {int index =getArguments().getInt("index", 0);return  index;}}


DetailActivity如下:

package cc.testsimplefragment2;import android.app.Activity;import android.content.res.Configuration;import android.os.Bundle;/** * 在此Activity中我们将一个Fragment嵌入到 * 该Activity中进行显示 */public class DetailActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//横屏的处理if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {finish();return;}        //竖屏的处理//此处的道理和TitleListFragment中对于横屏的//处理很相似,只是方式稍有差别.//1 生成设置好参数的DetailFragment//2 将此DetailFragment attach到当前的activityif (savedInstanceState == null) { DetailFragment detailFragment = new DetailFragment();detailFragment.setArguments(getIntent().getExtras()); getFragmentManager().beginTransaction().add(android.R.id.content, detailFragment).commit(); }}}


Data如下:

package cc.testsimplefragment2;public final class Data {//标题    public static final String[] TITLES = { "标题1","标题2", "标题3","标题4"};    //内容    public static final String[] DETAILS = { "内容1","内容2", "内容3","内容4"};}


layout/main.xml如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal" android:layout_width="match_parent"android:layout_height="match_parent"><fragment android:id="@+id/titles"class="cc.testsimplefragment2.TitleListFragment"android:layout_weight="1" android:layout_width="0px"android:layout_height="match_parent" /></LinearLayout>

 

layout-land/main.xml如下:

<?xml version="1.0" encoding="utf-8"?><!-- 横屏时的布局文件 --><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal" android:layout_width="match_parent"android:layout_height="match_parent"><fragment android:id="@+id/titles"class="cc.testsimplefragment2.TitleListFragment" android:layout_weight="1" android:layout_width="0px"android:layout_height="match_parent"      /><RelativeLayout     android:id="@+id/containerRelativeLayout"android:layout_weight="2" android:layout_width="0px"android:layout_height="match_parent" android:background="?android:attr/detailsElementBackground" /></LinearLayout>


AndroidManifest.xml如下:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="cc.testsimplefragment2"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk android:minSdkVersion="15" />    <application        android:icon="@drawable/ic_launcher"        android:label="@string/app_name" >        <activity            android:label="@string/app_name"            android:name="cc.testsimplefragment2.MainActivity" >            <intent-filter >                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>           <activity        android:name="cc.testsimplefragment2.DetailActivity"       android:label="详细内容的Activity"        />    </application></manifest>