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

简介: MainActivity如下: package cc.testsimplefragment2;import android.app.Activity;import android.

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 {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main); 
	}
	
	@Override
	protected 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()方法
	@Override
	public 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); 
		}
	}
	
	@Override
	public void onStart() {
		super.onStart();
		System.out.println("---> onStart");
	}
	
	//处理手机一直在竖屏时:
	//点击标题,跳转后,再按下back键的情况
	@Override
	public 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()方法
	@Override
	public void onSaveInstanceState(Bundle bundle) {
		super.onSaveInstanceState(bundle);
		bundle.putInt(currentCheckedKey, currentCheckedPosition);
		System.out.println("---> onSaveInstanceState()");
		System.out.println("---> onSaveInstanceState() currentCheckedPosition="+currentCheckedPosition);
	}

	
	//点击ListFragment上的某个条目时调用
	@Override
	public 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)原来的Fragment
				fragmentTransaction.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然后将其返回
	@Override
	public 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实例,并且保存index
	public static DetailFragment newInstance(int index) {
		DetailFragment detailFragment = new DetailFragment();
		Bundle bundle = new Bundle(); 
		bundle.putInt("index", index); 
		detailFragment.setArguments(bundle);
		return detailFragment;
	}

	//取出index
	public 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 {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//横屏的处理
		if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
			finish();
			return;
		}
        
		//竖屏的处理
		//此处的道理和TitleListFragment中对于横屏的
		//处理很相似,只是方式稍有差别.
		//1 生成设置好参数的DetailFragment
		//2 将此DetailFragment attach到当前的activity
		if (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>


 

相关文章
|
Android开发
【RecyclerView】 十四、GridLayoutManager 网格布局管理器 ( GridLayoutManager.SpanSizeLookup 指定 item 元素占用网格个数 )
【RecyclerView】 十四、GridLayoutManager 网格布局管理器 ( GridLayoutManager.SpanSizeLookup 指定 item 元素占用网格个数 )
1341 0
【RecyclerView】 十四、GridLayoutManager 网格布局管理器 ( GridLayoutManager.SpanSizeLookup 指定 item 元素占用网格个数 )
Cocos Creator3.8 项目实战(三)去除scrollview背景色和label 对齐方式设置无效问题解决
Cocos Creator3.8 项目实战(三)去除scrollview背景色和label 对齐方式设置无效问题解决
134 0
|
小程序
小程序:picker-view选择器快速滚动,确认时,”值显示错误“
小程序:picker-view选择器快速滚动,确认时,”值显示错误“
280 0
ViewPager 显示 两侧的View,各显示一点
ViewPager 显示 两侧的View,各显示一点
ViewPager 显示 两侧的View,各显示一点
【Flutter】GridView 网格布局 ( GridView.count 构造函数 | crossAxisCount 参数指定每行元素个数 )
【Flutter】GridView 网格布局 ( GridView.count 构造函数 | crossAxisCount 参数指定每行元素个数 )
507 0
【Flutter】GridView 网格布局 ( GridView.count 构造函数 | crossAxisCount 参数指定每行元素个数 )
|
测试技术 Android开发 容器
View位置参数与滑动全解析
一. View位置参数与坐标分析 View是Android中所有控件的基类,是一种界面层的控件的一种抽象,代表一个控件,常见的获取位置参数的方法有以下三种: 1.View的getTop(),getLeft(), getRight(),getBottom() View的位置主要由它的四个顶点来决定,分别对应View的四个属性:top,left,right,bottom,其中top是左上角纵坐标 ,left是左上角横坐标,right是右下角横坐标,bottom是右下角纵坐标。
1142 0
|
容器
ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示(优化篇)
上一张效果图: 之前的项目有一个Galley的项目,但是代码结构特别乱,别问我为什么,我也是刚接手这个项目,为了方便以后阅读和维护我对一些模块进行了重构。ViewPager实现Galler效果,但是当时时间比较急,写的比较仓促,上一篇实现了简单的效果,但是对于初始的时候左边滑动是有问题的,这是因为我们在自己的Adapter的时候对于getCount,我们想通过Integer.MAX_VAL
1712 0
|
Android开发
Android ListView子item高度定长固定值无效问题
在项目开发中遇到一个实际问题:ListView中,打算给每个子item设定一个具体的高度值如128dp,256dp,在子item中把根布局的高度值写死写成定长,但是不管怎么样,高度一直都没变化。
894 0