`
jean7155
  • 浏览: 62886 次
  • 性别: Icon_minigender_2
  • 来自: 上海
社区版块
存档分类
最新评论

Fragment开发实例

阅读更多
SVN源码下载地址: https://svn.codespot.com/a/eclipselabs.org/demo1/trunk/myAndroid2_2
或者请下载附件myAndroid2_2.rar.

说明:
这个实例原本是用ANDROID2.2开发的,因此取了2.2的名字。 现在, 该应用的ANDROID已经提升到4.0.

Fragment的使用
    android应用了一个UI设计理念:一个activity可以包含多个fragment。 比如实例中的国家管理模型, 当进入国家管理时(layout activity), 左边出现已经输入的国家列表(list fragment), 点击列表中的国家名称,右边则出现该国家的具体内容(details fragment)。 以上设计就是典型的 list-details 模式。

    这个模式不仅适用于水平展示的屏幕(landscape), 也适用于竖直展示的屏幕(portrait)。 当水平展示时,屏幕左侧是list, 右侧是details; 而竖直展示时,屏幕只显示list, 点击其中的具体内容,屏幕显示details.

实例中的代码解释:
1. CountryLayout.java          整个国家管理界面。 该界面提供了2个MENU,一个是返回主菜单(back), 另一个是添加菜单(new).

2. CountryListFragment.java    显示了所有的国家列表。

3. CountryDetailsFragment.java 显示了具体的国家内容。该界面提供了几个按钮: 在landscape情况下, 有修改(edit)按钮和删除(delete)按钮, 在portrait情况下,不仅有修改和删除两个按钮,还增加了返回列表(list)的按钮(to previous) 

4. CountryDialogFragment.java  显示了国家的操作界面,保存按钮保存(save)添加或修改的内容, 关闭按钮(close)关闭操作界面。

源码要点:
1. Activity和fragment之间的联系
1) 在fragment中建立接口,并利用fragment的onAttach生命周期建立activity和fragment的联系。
xxxfragment.java
public interface OnHeadlineSelectedListener {
        /** Called by HeadlinesFragment when a list item is selected */
        public void onArticleSelected(int position, long id);
        
    }
@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception.
        try {
            mCallback = (OnHeadlineSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }


2) 在activity中调用fragment建立的接口,并完成接口的具体实现方法
xxxactivity.java implement xxxFragment.OnHeadlineSelectedListener 
@Override
	public void onArticleSelected(int position, long id) {
   	
    	// Capture the article fragment from the activity layout
        CountryDetailsFragment articleFrag = (CountryDetailsFragment)
                getFragmentManager().findFragmentById(R.id.details);

        if (articleFrag != null) {
            articleFrag.updateArticleView(id);
        } else {
            newDetailsFragment(id);
        }
		
	}


2. 创建fragment时的要点
1) fragment管理器
// 找到管理器
 FragmentTransaction ft = getFragmentManager().beginTransaction();
// 将创建的details fragment替换原来的fragment。
        ft.replace(R.id.details, details);
        。。。。。。
//提交
        ft.commit();


2) 判断fragment是否存在
//通过ID寻找的方法
 CountryDetailsFragment details = (CountryDetailsFragment) getFragmentManager().findFragmentById(R.id.details);
// 还有一种是通过Tag来查找的,我这里暂时没有实例。


3) fragment中参数传递
Bundle bundle = new Bundle();
	    bundle.putLong("selectedId", id);
	    bundle.putBoolean("mDualPane", mDualPane);
// 将参数邦定fragment.
	    details.setArguments(bundle);


4) 创建fragment时UI元素的提取
View v = inflater.inflate(R.layout.area_details, container, false);
        	
        	text1 = (TextView) v.findViewById(R.id.areaName);
            text2 = (TextView) v.findViewById(R.id.areaDetails);
......


源码要点的实际应用:
1. 水平屏幕和竖直屏幕的设置(config landscape and portrait),

为了适应不同屏幕,android配置方法如下:
1) 在 res/values目录下增加layouts.xml(portrait配置), 在 res/values-land目录下也增加layouts.xml(landscape配置).

2) res/values/layouts.xml
<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <item name="country_layout" type="layout">@layout/country_onepane</item>
    <bool name="has_two_panes">false</bool>
</resources>


3) res/values-land/layouts.xml
<resources>
    <item name="country_layout" type="layout">@layout/country_twopane</item>
    <bool name="has_two_panes">true</bool>
</resources>


2. config fragment
2-1)  portrait配置: res/layout/country_onepane.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <fragment class="cn.com.demo.android.activity.CountryListFragment"
            android:id="@+id/titles"
            android:layout_width="match_parent" android:layout_height="match_parent" />
  
</LinearLayout> 


2-2)  portrait配置: res/layout-land/country_twopane.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <fragment class="cn.com.demo.android.activity.CountryListFragment"
            android:id="@+id/titles" android:layout_weight="1"
            android:layout_width="0px" android:layout_height="match_parent" />

    <FrameLayout android:id="@+id/details" android:layout_weight="1"
            android:layout_width="0px" android:layout_height="match_parent"
            android:background="?android:attr/detailsElementBackground" />
    
</LinearLayout>


3. layout activity: CountryLayout.java
1)  protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // 根据屏幕判断是调用landscape的xml文件,还是portrait的xml文件。 
        [i]setContentView(R.layout.country_layout);[/i]
        
        // mIsDualPane是判断屏幕是否为landscape的关键,它将作为一个参数传递给其它fragment. 
        View detailsFrame = findViewById(R.id.details);
        mIsDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE;
        
    }


2) 需要运行CountryListFragment.OnHeadlineSelectedListener接口方法
       public void onArticleSelected(int position, long id) {
   	
    	// 判断是否存在details fragment, 如果不存在,需要创建 details fragment. 
        CountryDetailsFragment articleFrag = (CountryDetailsFragment)
                getFragmentManager().findFragmentById(R.id.details);

        if (articleFrag != null) {
            articleFrag.updateArticleView(id);
        } else {
            newDetailsFragment(id);
        }
		
	}


3. list fragment
OnHeadlineSelectedListener mCallback;
1) 定义接口
public interface OnHeadlineSelectedListener {
        /** Called by HeadlinesFragment when a list item is selected */
        public void onArticleSelected(int position, long id);
        
    }


2) 按照android开发者网站的文档说明,这个onAttach方法是属于fragment的生命周期,用于和调用它的activity联系,以便activity能够调用它的接口。
  @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception.
        try {
            mCallback = (OnHeadlineSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }


3) 当列表中的具体项被点击时,显示details的方法。
@Override
    public void onListItemClick(ListView l, View v, int position, long id) {
    	
    	if(mDualPane){
    		mCallback.onArticleSelected(position, id);
    		getListView().setItemChecked(position, true);
    	}
    	showDetails(id);
    }


4) 显示details内容
void showDetails(long id){
        // 如果是landscape 屏幕, 直接显示detailsFragment, 如果是portrait屏幕,这显示detailsActivity.    	
    	if (mDualPane) {
            // Check what fragment is currently shown, replace if needed.
            CountryDetailsFragment details = (CountryDetailsFragment) getFragmentManager().findFragmentById(R.id.details);
            
            if(details==null || id==0){
            	this.newDetailsFragment(details, id);
            }else
            	details.updateArticleView(id);

    	}else{
    		this.newDetailsActivity(id);
    		
    	}
    }


4. details fragment
1) 创建details fragment时, 通过mDualPane判断,是landscape,还是portrait.
   @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
       
        ........        
        
        mDualPane = getArguments().getBoolean("mDualPane");
        
        if(mDualPane){
        	
                // landscape时fragment调用UI组件的方法。
        	View v = inflater.inflate(R.layout.area_details, container, false);
        	
        	text1 = (TextView) v.findViewById(R.id.areaName);
            text2 = (TextView) v.findViewById(R.id.areaDetails);
        	
        	previous = (Button) v.findViewById(R.id.country_toprevious);
        	delete = (Button) v.findViewById(R.id.country_delete);
        	edit = (Button) v.findViewById(R.id.country_edit);
        	
        	if(previous!=null) previous.setVisibility(View.GONE);
        	toggleButtons(View.INVISIBLE);
        	
        	if(delete!=null) delete.setOnClickListener(deleteMe);
        	if(edit!=null) edit.setOnClickListener(editMe);
        	
        	long _id = getArguments().getLong("selectedId");
        	if(_id>0) this.displayDetails(_id);
        	
        	return v;

        }else{
                // portrait时,activity调用UI组件的方法。(同intent调用方法)
        	getActivity().setContentView(R.layout.area_details);
        	
        	extras = getActivity().getIntent().getExtras();
        
        	previous = (Button) getActivity().findViewById(R.id.country_toprevious);
			delete = (Button) getActivity().findViewById(R.id.country_delete);
			edit = (Button) getActivity().findViewById(R.id.country_edit);
			
			if(previous!=null) previous.setOnClickListener(previousMe);
			if(delete!=null) delete.setOnClickListener(deleteMe);
        	if(edit!=null) edit.setOnClickListener(editMe);

        	display();
			
	        return null;
        }
        
        
    }


2) 调用dialog fragment的方法
void showDialog(){
    	
    	FragmentTransaction ft = getFragmentManager().beginTransaction();
	    Fragment prev = getFragmentManager().findFragmentByTag(COUNTRY_DIALOG_FRAGMENT);
	    if (prev != null) {
	        ft.remove(prev);
	    }
	    ft.addToBackStack(null);
	    
	    // Create and show the dialog.
	    DialogFragment newFragment = CountryDialogFragment.newInstance();
	    Bundle bundle = new Bundle();
	    bundle.putLong("selectedId", id);
	    bundle.putBoolean("mDualPane", mDualPane);
	    
	    newFragment.setArguments(bundle);
	    newFragment.show(ft, COUNTRY_DIALOG_FRAGMENT);
    	
    }

   
5. dialog fragment
   @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);

         // 设置dialog的显示style和theme
         int style = DialogFragment.STYLE_NORMAL, theme = android.R.style.Theme_Holo_Light;
         setStyle(style, theme);
         
         Bundle args = getArguments();
         if(args!=null) id = args.getLong("selectedId");
         if(args!=null) mDualPane = args.getBoolean("mDualPane");
         
         Log.i(TAG,"args is null:" + ((args==null)?true:false));

         ......         
     }
分享到:
评论

相关推荐

    Android Fragment实例

    在Android应用开发中,Fragment是Android SDK中的一个重要组件,它被设计用来支持多屏幕适配和增强用户界面的模块化。Fragment允许开发者将应用程序的功能或UI部分分解为独立的、可重用的组件,这些组件可以在不同的...

    Android Fragment相关实例

    在Android应用开发中,Fragment是Android SDK中的一个重要组件,它允许开发者在Activity中创建可重用的UI块。Fragment的设计使得应用能更好地适应多种屏幕尺寸和配置,如手机和平板。下面将详细介绍Fragment的使用、...

    Fragment应用实例

    在本教程中,我们将深入探讨Fragment的应用实例,帮助初学者理解其核心概念和使用方式。 首先,Fragment是UI组件,它们有自己的生命周期和UI布局。Fragment可以单独存在于Activity中,也可以与多个Fragment一起在一...

    炫酷Fragment实例二代码

    Fragment是Android应用开发中的一个重要组件,它是在Android 3.0(API级别11)引入的,用于在大型屏幕上创建动态、多面板的应用。在平板电脑等大屏幕设备上,Fragment使得开发者可以将一个Activity拆分成多个可独立...

    Android Studio动态加载Fragment和获取实例的方法

    然而,在实际开发中,我们经常需要动态加载 Fragment 和获取 Fragment 的实例,以满足不同的业务需求。 在本文中,我们将讨论如何在 Android Studio 中动态加载 Fragment 和获取 Fragment 的实例。我们将通过一个...

    Fragment实例

    在Android开发中,Fragment是自Android 3.0(API级别11)引入的一个关键组件,它极大地丰富了用户界面的设计和交互。Fragment是Activity的一部分,可以在Activity中动态添加、删除或替换,使得应用程序能够在不同...

    Fragment小实例

    Fragment是Android应用开发中的一个重要组件,它首次出现在Android 3.0(API级别11)中,被设计用来支持在大屏幕设备如平板电脑上构建更复杂的用户界面。Fragment可以理解为一个可嵌入到Activity中的小型独立应用...

    fragmentdemo简单实例

    以上就是"fragmentdemo简单实例"中涉及的主要Android Fragment开发知识点。通过这个实例,开发者可以学习如何在实际项目中有效地使用Fragment,提升用户体验,尤其是针对大屏幕设备的应用设计。

    Fragment实现tab实例

    在Android开发中,Fragment是应用UI模块化的重要组成部分,它允许开发者在Activity中添加和管理多个可交互的屏幕片段。本实例"Fragment实现tab"主要展示了如何使用Fragment和FragmentTabHost来创建一个带有标签切换...

    Fragment实例二(源码)

    Fragment是Android应用开发中的一个重要组件,它是在Android 3.0 (API级别11)引入的,用于在大型屏幕上创建可重用、模块化的UI组件。在这个实例中,我们将深入探讨Fragment的使用,特别是如何利用它来实现类似底部...

    Fragment实例一(源码)

    Fragment是Android应用开发中的一个重要组件,它是在Android 3.0 (API级别11)引入的,用于在大型屏幕上创建可重用、可组合的UI片段。Fragment的设计初衷是为了更好地支持平板电脑等大屏幕设备,但随着时间的发展,它...

    Android解决多个Fragment切换时布局重新实例化问题,并保存当前fragment页面,系统回收后还原之前fragment页面,更新版

    总之,避免Fragment在切换时重新实例化并保存其状态是Android开发中的常见挑战。通过巧妙地使用生命周期方法、ViewModel、回退栈和PagerAdapter,我们可以确保用户的交互体验不会因为界面的切换而中断,即使在系统...

    一个Android -Fragment实例

    在Android应用开发中,Fragment是Android SDK中的一个重要组件,它被设计用来支持多屏幕适配和复杂的用户界面设计。在大型应用中,尤其是在平板电脑和电视等大屏幕设备上,Fragment使得开发者能够将一个Activity拆分...

    Android Studio 导航栏开发 BottomNavigationView+Fragment 简单实例 适合新手

    Android Studio 导航栏开发 BottomNavigationView+Fragment 简单实例 https://blog.csdn.net/nujun1222/article/details/80079345

    动态加载Fragment实例源码

    在Android应用开发中,Fragment是UI组件的重要组成部分,它允许我们构建可重用、模块化的用户界面。在大型复杂的应用中,尤其是平板应用或者需要多种布局的手机应用,动态加载Fragment变得尤为关键。动态加载意味着...

    Fragment与Activity之间通信实例

    在Android应用开发中,Fragment和Activity是两个核心组件,它们共同构建了用户界面。Fragment代表一个可重用的UI部分,而Activity则是程序中的一个窗口,它可以包含一个或多个Fragment。Fragment与Activity之间的...

Global site tag (gtag.js) - Google Analytics