一款安卓应用,好歹也是一个系统啊,既然称得上是系统,就要考虑系统的稳定性,功能模块的耦合性,复用程度等等,所以一个好的开发模型必然达到事半功倍的效果。
目前(2015年11月),常见的手机应用基本上是登录之后是一个主页,首页里面嵌套着多个fragment或者view,fragment会采用缓存策略,点击里面的控件,例如按钮,图片,会弹出一个新的activity,负责给用户提供特定的服务。最为关键的是主页,主页显示的内容通常是比较全面的,数据很多,例如微信的主页,下面是4个tab(微信,通讯录,发现,我),每点击一个tab,tab上面内容都会切换到对应的Fragment或者view里面。无论它们怎么切换,都在同一个activity里面,这个activity就是主activity,我习惯的命名是MainAcitivity。除了MainActivity,其他新建的Activity,一般用户要求是有统一标题栏风格,这个时候就要考虑写一个activity的基类BaseActivity。然后所有的Activity都是这个基类的子类,如果后期需要修改风格(比如切换皮肤什么的)只要修改基类就可以了。
BaseActivity基类,负责处理窗口切换的动画效果,手势,图片资源回收等,是对activity的第一层封装
package com.example.activitymode; import java.util.ArrayList; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.RelativeLayout; /** * 基础Activity * 处理窗口切换动画,手势,回收图片资源等 * */ public class BaseActivity extends FragmentActivity { final int RIGHT = 0; final int LEFT = 1; protected GestureDetector gestureDetector; protected RelativeLayout mChildContent; /** * 是否执行界面切换动画 */ protected boolean isAnimation = true; private Context mContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mContext = this; requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置切换窗口的模式 getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); gestureDetector = new GestureDetector(this, onGestureListener); } @Override public void setContentView(int layoutResID) { // TODO Auto-generated method stub super.setContentView(R.layout.base_layout); mChildContent = (RelativeLayout) findViewById(R.id.main_content); View childView = LayoutInflater.from(this).inflate(layoutResID, mChildContent); } /** * 开启窗口的动画模式,左右切换 */ @Override public void startActivity(Intent intent) { // TODO Auto-generated method stub super.startActivity(intent); if (isAnimation) { overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); } } /** * 跳转到新窗口时,根据结果实现回退 */ @Override public void startActivityForResult(Intent intent, int requestCode) { // TODO Auto-generated method stub super.startActivityForResult(intent, requestCode); if (isAnimation) { overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); } } @Override public void finish() { // TODO Auto-generated method stub super.finish(); if (isAnimation) { overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out); } } private GestureDetector.OnGestureListener onGestureListener = new GestureDetector.SimpleOnGestureListener() { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (e2 == null || e1 == null) { return false; } if (e2.getX() - e1.getX() > 20 && Math.abs(velocityX) > 0) { } else if (e1.getX() - e2.getX() > 20 && Math.abs(velocityX) > 0) { } else return false; return true; } }; public boolean onTouchEvent(MotionEvent event) { return gestureDetector.onTouchEvent(event); } /** 顶部功能菜单被点击,子类实现此方法处理点击的具体操作 */ public void topOpermenuClicked() { } @Override protected void onPause() { super.onPause(); if (baseReceiver != null) unregisterReceiver(baseReceiver); } // 动态注册的广播接收器,当有接收到广播的时候,可以根据广播的action进行相应的操作 // 子类也可以绑定自己的动态广播接收器 protected BaseReceiver baseReceiver; @Override protected void onResume() { super.onResume(); if (baseReceiver == null) baseReceiver = new BaseReceiver(); IntentFilter filter = new IntentFilter(baseReceiver.ACTION); registerReceiver(baseReceiver, filter); } // Activity销毁 @Override protected void onDestroy() { super.onDestroy(); } /** * 回收View * * @param v */ public void destroyLevelListView(View v) { if (v == null) return; Drawable lld = v.getBackground(); if (lld == null) return; lld.setCallback(null); lld = null; v = null; } /** * 回收图片 * * @param v * @param recycle */ public void destroyBackground(View v, boolean recycle) { if (v == null) return; BitmapDrawable bd = (BitmapDrawable) v.getBackground(); if (bd == null) return; bd.setCallback(null); if (recycle) bd.getBitmap().recycle(); bd = null; v = null; } /** * 回收图片 * * @param v * @param recycle */ public void destroyDrawable(BitmapDrawable bd, boolean recycle) { if (bd == null) return; bd.setCallback(null); if (recycle) bd.getBitmap().recycle(); bd = null; } /** * 回收图片 * * @param v * @param recycle */ public void destroyDrawable(Drawable bd) { if (bd == null) return; bd.setCallback(null); bd = null; } /** * 回收界面控件 * * @param v * @param recycle */ public void destroyViews(View views[]) { if (views == null || views.length == 0) return; for (View view : views) { destroyViews(view, false); } } /** * 回收界面控件 * * @param v * @param recycle */ public void destroyViews(View rootView, boolean recycle) { if (rootView == null) return; ArrayList<View> views = rootView.getTouchables(); if (views != null && !views.isEmpty()) { for (View view : views) destroyView(view, recycle); } destroyView(rootView, recycle); } /** * 回收界面控件 * * @param v * @param recycle */ public void destroyViews(View rootView) { if (rootView == null) return; ArrayList<View> views = rootView.getTouchables(); if (views != null && !views.isEmpty()) { for (View view : views) destroyView(view); } destroyView(rootView); } /** * 回收界面控件 * * @param v * @param recycle */ public void destroyView(View view) { if (view == null) return; Drawable bd = view.getBackground(); destroyDrawable(bd); view = null; } /** * 回收界面控件 * * @param v * @param recycle */ public void destroyView(View view, boolean recycle) { if (view == null) return; Drawable bd = view.getBackground(); if (recycle) destroyBackground(bd); else destroyDrawable(bd); view = null; } /** * 回收界面控件 * * @param v * @param recycle */ private void destroyBackground(Drawable bd) { if (bd == null) { return; } if (bd instanceof BitmapDrawable) destroyDrawable((BitmapDrawable) bd, true); else destroyDrawable(bd); bd = null; } }
BaseActivity的布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <RelativeLayout android:id="@+id/main_content" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" > </RelativeLayout> </LinearLayout>
通用窗口类CommoneActivity,继承于BaseActivity,集中处理统一的标题栏,非首页的Acititvy都应该继承它,
如本例中的MoreActivity
package com.example.activitymode; import android.graphics.Color; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; /** * 集中处理标题 * @author cgx * */ public class CommonActivity extends BaseActivity { protected LinearLayout llhead, llBack, llMenu; protected RelativeLayout rlcontent, rlRoot; protected TextView tvback, tvtitle, tvmenu; /** * 是否覆盖头部,默认不覆盖 */ protected boolean isOverridehead = false; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); } public void setContentView(int layoutResID, boolean isOverridehead) { this.isOverridehead = isOverridehead; this.setContentView(layoutResID); } @Override public void setContentView(int layoutResID) { // TODO Auto-generated method stub super.setContentView(R.layout.common_activity_base_layout); rlRoot = (RelativeLayout) findViewById(R.id.child_main); llhead = (LinearLayout) findViewById(R.id.child_head); rlcontent = (RelativeLayout) findViewById(R.id.chid_content); tvback = (TextView) findViewById(R.id.child_back_text); llBack = (LinearLayout) findViewById(R.id.child_back_layout); tvtitle = (TextView) findViewById(R.id.child_title_text); tvmenu = (TextView) findViewById(R.id.child_menu_text); llMenu = (LinearLayout) findViewById(R.id.child_menu_layout); if (!isOverridehead) { View chidview = LayoutInflater.from(this).inflate(layoutResID, rlcontent); } else { View chidview = LayoutInflater.from(this) .inflate(layoutResID, null); rlRoot.addView(chidview, 0); llhead.setBackgroundResource(Color.parseColor("#00000000")); } llBack.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub finish(); } }); setMenuVisibility(View.INVISIBLE); } public void setHeadVisibility(int visible) { llhead.setVisibility(visible); } public void setTitle(String title) { tvtitle.setText(title); } public void setMenuVisibility(int visible) { llMenu.setVisibility(visible); } @Override public void setTitle(CharSequence title) { // TODO Auto-generated method stub setTitle(title.toString()); } public void setMenuText(String text) { this.tvmenu.setText(text); } public void setMenuBK(int id) { this.tvmenu.setBackgroundResource(id); } public void setOnMenuClickListen(OnClickListener onclicklistener) { this.llMenu.setOnClickListener(onclicklistener); } @Override public void setTitle(int titleId) { // TODO Auto-generated method stub setTitle(getText(titleId).toString()); } }
通用窗口类CommonActivity的布局文件,新建窗口需要继承于它
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/child_main" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFF" android:orientation="vertical" > <LinearLayout android:id="@+id/child_head" android:layout_width="match_parent" android:layout_height="50dp" android:background="#654321" android:orientation="horizontal" > <LinearLayout android:id="@+id/child_back_layout" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:paddingLeft="12dp" android:paddingRight="12dp" > <TextView android:id="@+id/child_back_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/comeback" android:gravity="center" android:text="" android:textColor="#ffffff" android:textSize="14dp" /> </LinearLayout> <TextView android:id="@+id/child_title_text" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="标题" android:textColor="#ffffff" android:textSize="17dp" /> <LinearLayout android:id="@+id/child_menu_layout" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:paddingLeft="12dp" android:paddingRight="12dp" > <TextView android:id="@+id/child_menu_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/main_more_icon" android:gravity="center" android:text="" android:textColor="#ffffff" android:textSize="14dp" /> </LinearLayout> </LinearLayout> <RelativeLayout android:id="@+id/chid_content" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/child_head" /> </RelativeLayout>
首页MainActivity,内嵌了四个fragment,MainActivity直接继承于BaseActivity,制定属于首页的标题栏(导航栏)
package com.example.activitymode; import java.util.ArrayList; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Color; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends BaseActivity { private static final String TAG = "MainActivity"; private ViewPager vpContent; private MainFragmentAdapter mFragmentAdapter; private CommonFragmentSaveStatePagerAdapter myFragmentSaveStatePagerAdapter; private ArrayList<CommonFragment> mFragments; private ArrayList<String> mTitles; Context mContext; TextView tv1, tv2, tv3, tv4, tvmenu; LinearLayout llMenu; MyFragment1 mFragment1; MyFragment2 mFragment2; MyFragment3 mFragment3; MyFragment4 mFragment4; // ImageView ivCursor; /** * 主页四个page “第一个”page */ public static final int FIRST_PAGE = 0; /** * “第二个”page */ public static final int SECOND_PAGE = 1; /** * “第三个”page */ public static final int THIRD_PAGE = 2; /** * "第四个"page */ public static final int FOURTH_PAGE = 3; private boolean isRegisterBroadcast = false; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); mContext = this; setContentView(R.layout.main_layout); initView(); initPageView(); initEvent(); initApp(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); } private void initView() { vpContent = (ViewPager) findViewById(R.id.v50_main_viewpager); tv1 = (TextView) findViewById(R.id.main_text1); tv1.setTextColor(Color.parseColor("#FFFF00")); tv2 = (TextView) findViewById(R.id.main_text2); tv3 = (TextView) findViewById(R.id.main_text3); tv4 = (TextView) findViewById(R.id.main_text4); tvmenu = (TextView) findViewById(R.id.main_menu_text); llMenu = (LinearLayout) findViewById(R.id.main_menu_layout); } private void initEvent() { // TODO Auto-generated method stub tv1.setOnClickListener(mClickListener); tv2.setOnClickListener(mClickListener); tv3.setOnClickListener(mClickListener); tv4.setOnClickListener(mClickListener); llMenu.setOnClickListener(mClickListener); vpContent.setOnPageChangeListener(mPageChangeListener); } private OnClickListener mClickListener = new OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.main_text1:// 第一个page setCurPage(FIRST_PAGE); break; case R.id.main_text2:// 第二个page setCurPage(SECOND_PAGE); break; case R.id.main_text3:// 第三个page setCurPage(THIRD_PAGE); break; case R.id.main_text4:// 第四个page setCurPage(FOURTH_PAGE); break; case R.id.main_menu_layout:// 菜单 IntentToMoreActivity(); break; default: break; } } }; public void setCurPage(int page) { vpContent.setCurrentItem(page, false); } private OnPageChangeListener mPageChangeListener = new OnPageChangeListener() { @Override public void onPageSelected(int arg0) { chosenTab(arg0); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // TODO Auto-generated method stub } @Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } }; private void chosenTab(int currentItem) { tv1.setTextColor(Color.parseColor("#FFFFFF")); tv2.setTextColor(Color.parseColor("#FFFFFF")); tv3.setTextColor(Color.parseColor("#FFFFFF")); tv4.setTextColor(Color.parseColor("#FFFFFF")); switch (currentItem) { case FIRST_PAGE: tv1.setTextColor(Color.parseColor("#FFFF00")); break; case SECOND_PAGE: tv2.setTextColor(Color.parseColor("#FFFF00")); break; case THIRD_PAGE: tv3.setTextColor(Color.parseColor("#FFFF00")); break; case FOURTH_PAGE: tv4.setTextColor(Color.parseColor("#FFFF00")); break; default: break; } } private void initPageView() { // TODO Auto-generated method stub mFragment1 = new MyFragment1(); mFragment2 = new MyFragment2(); mFragment3 = new MyFragment3(); mFragment4 = new MyFragment4(); mFragments = new ArrayList<CommonFragment>(); mFragments.add(mFragment1); mFragments.add(mFragment2); mFragments.add(mFragment3); mFragments.add(mFragment4); mTitles = new ArrayList<String>(); mTitles.add(mFragment1.getTitle()); mTitles.add(mFragment2.getTitle()); mTitles.add(mFragment3.getTitle()); mTitles.add(mFragment4.getTitle()); mFragmentAdapter = new MainFragmentAdapter(getSupportFragmentManager(), mFragments, mTitles); myFragmentSaveStatePagerAdapter = new CommonFragmentSaveStatePagerAdapter( getSupportFragmentManager(), vpContent, mFragments); vpContent.setAdapter(myFragmentSaveStatePagerAdapter); // 设置默认的窗口,就是打开应用后第一眼看到的 setCurPage(FIRST_PAGE); // 如果系统内存足够,就能实现fragment的缓存,参数是最大缓存数,如果数据量太大,就不要这样设置,耗内存 // vpContent.setOffscreenPageLimit(5); } /** 开启系统设置页面 **/ protected void IntentToMoreActivity() { // TODO Auto-generated method stub Intent intent = new Intent(MainActivity.this, MoreActivity.class); startActivity(intent); } /** * 初始化app */ private void initApp() { } /** 注册配置请求完成广播 */ public void registerBoradcastReceiver() { IntentFilter myIntentFilter = new IntentFilter(); myIntentFilter.addAction("main_action"); // 注册广播 this.registerReceiver(mBroadcastReceiver, myIntentFilter); isRegisterBroadcast = true; } /** 取消注册的广播 */ public void unRegisterBoradcastReceiver() { if (isRegisterBroadcast) { this.unregisterReceiver(mBroadcastReceiver); } } /** 广播接收器 */ private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String action = intent.getAction(); // 执行接受到广播后的相关操作,可以操作UI,但不能进行耗时操作 } }; /** * 跳转到对应的activity * * @param c */ public void intentToActivity(Class c) { if (c == null) { return; } Intent intent = new Intent(this, c); startActivity(intent); } public void intentToActivityForResult(int requestCode, Class c) { if (c == null) { return; } Intent intent = new Intent(mContext, c); ((Activity) mContext).startActivityForResult(intent, requestCode); } public void onActivityResult(int requestCode, int resultCode, Intent data) { } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub if (keyCode == KeyEvent.KEYCODE_BACK) { // 如果有提示退出对话框,可以在这里写代码 finish(); return true; } return super.onKeyDown(keyCode, event); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); } /** * 隐藏应用,返回到桌面 */ public void hide() { // 保存设置信息 Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } }
首页的布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/main_head" android:layout_width="match_parent" android:layout_height="50dp" android:background="#654321" android:orientation="horizontal" android:paddingLeft="12dp" android:paddingRight="12dp" > <TextView android:id="@+id/main_text1" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="page1" android:textColor="#b3ffffff" android:textSize="15dp" /> <TextView android:id="@+id/main_text2" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="page2" android:textColor="#b3ffffff" android:textSize="15dp" /> <TextView android:id="@+id/main_text3" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="page3" android:textColor="#b3ffffff" android:textSize="15dp" /> <TextView android:id="@+id/main_text4" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="page4" android:textColor="#b3ffffff" android:textSize="15dp" /> <LinearLayout android:id="@+id/main_menu_layout" android:layout_width="50dp" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" > <TextView android:id="@+id/main_menu_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/main_more_icon" android:gravity="center" android:textColor="#ffffff" /> </LinearLayout> </LinearLayout> <android.support.v4.view.ViewPager android:id="@+id/v50_main_viewpager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/main_head" /> </RelativeLayout>
关于fragment,实现了滑动切换的效果,需要对Fragment进行封装,封装后的类名是CommonFragment,添加滑动效果
package com.example.activitymode; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; public class CommonFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub return super.onCreateView(inflater, container, savedInstanceState); } @Override public void startActivity(Intent intent) { super.startActivity(intent); getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); } @Override public void startActivityForResult(Intent intent, int requestCode) { super.startActivityForResult(intent, requestCode); getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { // TODO Auto-generated method stub } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // TODO Auto-generated method stub } @Override public void onResume() { // TODO Auto-generated method stub super.onResume(); } @Override public void onPause() { // TODO Auto-generated method stub super.onPause(); } public void onBackPressed() { } public void onTabChange() { } }
首页里面的一个Fragment,由于其他3个都是类似的,所以只提供一个代码
package com.example.activitymode; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class MyFragment1 extends CommonFragment { public static String title = "MyFragment1"; private View rootView; public String getTitle() { // TODO Auto-generated method stub return title; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub rootView = inflater .inflate(R.layout.fragment1_layout, container, false); return rootView; } }
布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#123456" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textColor="#ffffff" android:text="The first page" /> </LinearLayout>
适配器:
CommonFragmentPagerAdapter
viewpager的fragment適配器,fragment管理类FragmentManager,不显示的fragment采取销毁策略
缓存策略为显示页面左边第一个以及右边第一个
package com.example.activitymode; import java.util.ArrayList; import java.util.List; import android.os.Parcelable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.PagerAdapter; import android.view.View; import android.view.ViewGroup; /** * viewpager的fragment適配器,fragment管理类FragmentManager,自带缓存策略的适配器, * 缓存策略为显示页面左边第一个以及右边第一个 * * */ public abstract class CommonFragmentPagerAdapter extends PagerAdapter { private static final String TAG = "CommonFragmentPagerAdapter"; private final FragmentManager mFragmentManager; private FragmentTransaction mCurTransaction = null; private Fragment mCurrentPrimaryItem = null; private List<Fragment> mFragments; public CommonFragmentPagerAdapter(FragmentManager fm) { mFragmentManager = fm; } public CommonFragmentPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragments) { mFragmentManager = fm; this.mFragments = fragments; } public abstract Fragment getItem(int position); @Override public int getCount() { return mFragments.size(); } @Override public int getItemPosition(Object object) { return super.getItemPosition(object); } @Override public void startUpdate(View container) { } @Override public Object instantiateItem(View container, int position) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } final long itemId = getItemId(position); String name = makeFragmentName(container.getId(), itemId); Fragment fragment = mFragmentManager.findFragmentByTag(name); if (fragment != null) { // mCurTransaction.detach(fragment); mCurTransaction.attach(fragment); } else { fragment = getItem(position); mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId)); } if (fragment != mCurrentPrimaryItem) { fragment.setMenuVisibility(false); fragment.setUserVisibleHint(false); } return fragment; } @Override public void destroyItem(View container, int position, Object object) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } mCurTransaction.detach((Fragment) object); } @Override public void setPrimaryItem(ViewGroup container, int position, Object object) { // TODO Auto-generated method stub Fragment fragment = (Fragment) object; if (fragment != mCurrentPrimaryItem) { if (mCurrentPrimaryItem != null) { mCurrentPrimaryItem.setMenuVisibility(false); mCurrentPrimaryItem.setUserVisibleHint(false); } if (fragment != null) { fragment.setMenuVisibility(true); fragment.setUserVisibleHint(true); } mCurrentPrimaryItem = fragment; } super.setPrimaryItem(container, position, object); } @Override public void finishUpdate(View container) { if (mCurTransaction != null) { mCurTransaction.commitAllowingStateLoss(); mCurTransaction = null; mFragmentManager.executePendingTransactions(); } } @Override public boolean isViewFromObject(View view, Object object) { return ((Fragment) object).getView() == view; } @Override public Parcelable saveState() { // TODO Auto-generated method stub return null; } public long getItemId(int position) { return position; } private static String makeFragmentName(int viewId, long id) { return "android:switcher:" + viewId + ":" + id; } @Override public void notifyDataSetChanged() { // TODO Auto-generated method stub // if (mCurTransaction == null) { // mCurTransaction = mFragmentManager.beginTransaction(); // } // final long itemId = getItemId(position); // String name = makeFragmentName(container.getId(), itemId); // Fragment fragment = mFragmentManager.findFragmentByTag(name); // if (fragment != null) { // mCurTransaction.detach(fragment); // mCurTransaction.attach(fragment); // } super.notifyDataSetChanged(); } }
package com.example.activitymode; import java.util.List; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.View; import android.view.ViewGroup; public class CommonFragmentSaveStatePagerAdapter extends PagerAdapter { private List<CommonFragment> fragments; private FragmentManager fragmentManager; private ViewPager viewPager; private int currentPageIndex = 0; private OnExtraPageChangeListener onExtraPageChangeListener; public CommonFragmentSaveStatePagerAdapter(FragmentManager fragmentManager, ViewPager viewPager, List<CommonFragment> fragments) { this.fragments = fragments; this.fragmentManager = fragmentManager; this.viewPager = viewPager; this.viewPager.setAdapter(this); this.viewPager.setOnPageChangeListener(mOnPageChangeListener); } @Override public int getCount() { return fragments.size(); } @Override public boolean isViewFromObject(View view, Object o) { return view == o; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(fragments.get(position).getView()); // 移出viewpager两边之外的page布局 } @Override public Object instantiateItem(ViewGroup container, int position) { Fragment fragment = fragments.get(position); if (!fragment.isAdded()) { FragmentTransaction ft = fragmentManager.beginTransaction(); ft.add(fragment, fragment.getClass().getSimpleName()); ft.commit(); /** * 在用FragmentTransaction.commit()方法提交FragmentTransaction对象后 * 会在进程的主线程中,用异步的方式来执行。 如果想要立即执行这个等待中的操作,就要调用这个方法(只能在主线程中调用)。 * 要注意的是,所有的回调和相关的行为都会在这个调用中被执行完成,因此要仔细确认这个方法的调用位置。 */ fragmentManager.executePendingTransactions(); } if (fragment.getView().getParent() == null) { container.addView(fragment.getView()); } return fragment.getView(); } public int getCurrentPageIndex() { return currentPageIndex; } public OnExtraPageChangeListener getOnExtraPageChangeListener() { return onExtraPageChangeListener; } public void setOnExtraPageChangeListener( OnExtraPageChangeListener onExtraPageChangeListener) { this.onExtraPageChangeListener = onExtraPageChangeListener; } private OnPageChangeListener mOnPageChangeListener = new OnPageChangeListener() { @Override public void onPageSelected(int arg0) { // TODO Auto-generated method stub fragments.get(currentPageIndex).onPause(); if (fragments.get(arg0).isAdded()) { fragments.get(arg0).onResume(); } currentPageIndex = arg0; if (null != onExtraPageChangeListener) { onExtraPageChangeListener.onExtraPageSelected(arg0); } } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub if (null != onExtraPageChangeListener) { onExtraPageChangeListener.onExtraPageScrolled(arg0, arg1, arg2); } } @Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub if (null != onExtraPageChangeListener) { onExtraPageChangeListener.onExtraPageScrollStateChanged(arg0); } } }; static class OnExtraPageChangeListener { public void onExtraPageScrolled(int i, float v, int i2) { } public void onExtraPageSelected(int i) { } public void onExtraPageScrollStateChanged(int i) { } } }
其他非首页的Activity,这里的试例是MoreActivity
package com.example.activitymode; import android.os.Bundle; public class MoreActivity extends CommonActivity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.more_activity_layout); setTitle("菜单"); } }
布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="Menu activity" android:gravity="center" android:background="#ffffff"/> </LinearLayout>
demo项目代码
http://pan.baidu.com/s/1i3o9bVJ