參考文章
【1】http://www.cnblogs.com/beenupper/archive/2012/07/13/2589749.html
【2】http://www.cnblogs.com/beenupper/archive/2012/07/18/2597504.html
功能需求:在初次加載每個Activity時,頁面載入不同的引導界面。
思路:
1、每個Activity動作都一樣,所以必須封裝一個BaseActivity,在onStart()方法中實現加載引導頁,並對外提供加載接口。其他Activity extends BaseActivity
2、只需要初次加載時顯示引導頁,所以引入SharedPreferences,用於保存該Activity是否為初次加載
由於引導過的界面就沒必要再次引導了。所以得保存記錄。這里采用偏好設置保存,如果該Activity被引導過了,就將它的類全名保存下。
由於偏好設置只能保存鍵值(key-value)對,所以保存多個類名,我采用|a|b|c這種形式保存為value。
3、顯示引導頁其實就是展示一個全屏的ImageView,在UI上體現為FrameLayout動態加載一個圖層,當不需要時remove
4、怎樣獲取每個Activity這個啥啥FrameLayout?可以考慮使用DecorView(DecorView為整個Window界面的最頂層View,相關介紹見參考文章【1】)。
只需要解決怎么找到那個Framelayout,我這里想到的辦法是給每個xml布局的根元素設置一個id,通過findViewById找到咋們通過setContentView設置上布局,
再通過View的view.getParent();得到它的父元素。它的父元素不就是咋們的要的FrameLayout嗎?
然后創建一個ImageView設置上引導圖片加到FrameLayout就可以了
直接上代碼吧。
(1)實現MyPreferences.java。實現保持Activity是否為初次加載。
package com.amanda.guidetest; import android.content.Context; public class MyPreferences { //偏好文件名 public static final String SHAREDPREFERENCES_NAME = "my_pref"; //引導界面KEY private static final String KEY_GUIDE_ACTIVITY = "guide_activity"; /** * 判斷activity是否引導過 * * @param context * @return 是否已經引導過 true引導過了 false未引導 */ public static boolean activityIsGuided(Context context,String className){ if(context==null || className==null||"".equalsIgnoreCase(className))return false; String[] classNames = context.getSharedPreferences(SHAREDPREFERENCES_NAME, Context.MODE_WORLD_READABLE) .getString(KEY_GUIDE_ACTIVITY, "").split("\\|");//取得所有類名 如 com.my.MainActivity for (String string : classNames) { if(className.equalsIgnoreCase(string)){ return true; } } return false; } /**設置該activity被引導過了。 將類名已 |a|b|c這種形式保存為value,因為偏好中只能保存鍵值對 * @param context * @param className */ public static void setIsGuided(Context context,String className){ if(context==null || className==null||"".equalsIgnoreCase(className))return; String classNames = context.getSharedPreferences(SHAREDPREFERENCES_NAME, Context.MODE_WORLD_READABLE) .getString(KEY_GUIDE_ACTIVITY, ""); StringBuilder sb = new StringBuilder(classNames).append("|").append(className);//添加值 context.getSharedPreferences(SHAREDPREFERENCES_NAME, Context.MODE_WORLD_READABLE)//保存修改后的值 .edit() .putString(KEY_GUIDE_ACTIVITY, sb.toString()) .commit(); } }
(2)修改BaseActivity.java。實現動態加載引導界面,並提供接口。
package com.amanda.guidetest; import android.app.Activity; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ImageView.ScaleType; public class BaseActivity extends Activity { private int guideResourceId=0;//引導頁圖片資源id @Override protected void onStart() { super.onStart(); addGuideImage();//添加引導頁 } /** * 添加引導圖片 */ public void addGuideImage() { View view = getWindow().getDecorView().findViewById(R.id.my_content_view);//查找通過setContentView上的根布局 if(view==null)return; if(MyPreferences.activityIsGuided(this, this.getClass().getName())){ //引導過了 return; } ViewParent viewParent = view.getParent(); if(viewParent instanceof FrameLayout){ final FrameLayout frameLayout = (FrameLayout)viewParent; if(guideResourceId!=0){//設置了引導圖片 final ImageView guideImage = new ImageView(this); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT); guideImage.setLayoutParams(params); guideImage.setScaleType(ScaleType.FIT_XY); guideImage.setImageResource(guideResourceId); guideImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { frameLayout.removeView(guideImage); MyPreferences.setIsGuided(getApplicationContext(), BaseActivity.this.getClass().getName());//設為已引導 } }); frameLayout.addView(guideImage);//添加引導圖片 } } } /**子類在onCreate中調用,設置引導圖片的資源id *並在布局xml的根元素上設置android:id="@id/my_content_view" * @param resId */ protected void setGuideResId(int resId){ this.guideResourceId=resId; } }
(3)修改Activity(例如MainActivity)的xml布局文件,在最頂層布局layout中加入id:my_content_view
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:id="@id/my_content_view"> <TextView android:id="@+id/txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/hello_world" /> <Button android:id="@+id/btn_close" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/txt" android:text="@string/btn_back"> </Button> </RelativeLayout>
(4)修改res/values/ids.xml,增加id
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android"> <item type="id" name="my_content_view"></item> </resources>
(5)在MainActivity.java的onCreate()中調用接口setGuideResId(),設置要加載的引導界面圖片
package com.amanda.guidetest; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.widget.Button; public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button)findViewById(R.id.btn_close); btn.setText(this.getString(R.string.btn_go)); btn.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this, SubActivity.class)); } }); setGuideResId(R.drawable.yindao01);//添加引導頁 } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
(6)最后,上幾張圖片吧
總結(重要部分,已用紅色標明):
(1)增加MyPreferences.java
(2)修改BaseActivity.java
(3)修改res/values/ids.xml
(4)在需要加載引導界面的Activity的布局文件中,在最頂層布局layout中加入id,android:id="@id/my_content_view"
(5)在需要加載引導界面的Activity的java代碼中,調用接口setGuideResId(),如setGuideResId(R.drawable.yindao01)