一款安卓應用,好歹也是一個系統啊,既然稱得上是系統,就要考慮系統的穩定性,功能模塊的耦合性,複用程度等等,因此一個好的開發模型必然達到事半功倍的效果。java
目前(2015年11月),常見的手機應用基本上是登陸以後是一個主頁,首頁裏面嵌套着多個fragment或者view,fragment會採用緩存策略,點擊裏面的控件,例如按鈕,圖片,會彈出一個新的activity,負責給用戶提供特定的服務。最爲關鍵的是主頁,主頁顯示的內容一般是比較全面的,數據不少,例如微信的主頁,下面是4個tab(微信,通信錄,發現,我),每點擊一個tab,tab上面內容都會切換到對應的Fragment或者view裏面。不管它們怎麼切換,都在同一個activity裏面,這個activity就是主activity,我習慣的命名是MainAcitivity。除了MainActivity,其餘新建的Activity,通常用戶要求是有統一標題欄風格,這個時候就要考慮寫一個activity的基類BaseActivity。而後全部的Activity都是這個基類的子類,若是後期須要修改風格(好比切換皮膚什麼的)只要修改基類就能夠了。android
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都應該繼承它,app
如本例中的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的佈局文件,新建窗口須要繼承於它ide
<?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,添加滑動效果this
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