1. 程式人生 > >PopupWindow的各種用法(二)——使用PopupWindow做一個指引蒙板(帶啟動頁,仿ViewPager滾動的引導頁)

PopupWindow的各種用法(二)——使用PopupWindow做一個指引蒙板(帶啟動頁,仿ViewPager滾動的引導頁)

引言:接下來和大家分享一下用一個PopupWindow來做一個指引蒙板的效果。鑑於網上對於“指引蒙板”的實現例子不是太多(或者是我找不到更多的),而且好像有很多的例子都是用一個Frame佈局+Fragment去完成,對於這種做法自己不太喜歡,於是突發奇想的想要自己用PopupWindow去實現。結果也是能做出自己先要的效果的。而且自己想要的功能也都實現了,使我覺得PopupWindow在真實專案中的應用還是挺廣泛的。廢話就到這裡,下面是小量的講解與程式碼的實現。

和上次一樣,首先來了解一下專案的結構:


接著是專案的第一部分圖片:


一、啟動頁和3張引導頁:

public class 
SplashActivity extends Activity { boolean isFirstIn = false; private static final int GO_HOME = 1000; private static final int GO_GUIDE = 1001; //延遲一秒 private static final long SPALSH_DELAY_MILLIS = 1000; private static final String SHAREDPREFERENCES_FIRST_ENTER = "first_enter"; private Handler mHandler
= new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case GO_GUIDE: goGuide(); break; case GO_HOME: goHome(); break; } super
.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); init(); } private void init() { //讀取SharePreferences中需要的資料 //使用Sharepreferences來記錄程式的使用次數 SharedPreferences preferences = getSharedPreferences(SHAREDPREFERENCES_FIRST_ENTER, MODE_PRIVATE); //取得相應的值,如果沒有該值,說明還沒寫入,用true來作為預設值 isFirstIn = preferences.getBoolean("isFirstIn", true); //判斷程式是第幾次執行,如果是第一次執行則跳轉到引導介面,否則跳轉到主介面 if (!isFirstIn) { //使用Handler的postDelayed方法,3秒後執行跳轉到MainActivity mHandler.sendEmptyMessageDelayed(GO_HOME, SPALSH_DELAY_MILLIS); } else { mHandler.sendEmptyMessageDelayed(GO_GUIDE, SPALSH_DELAY_MILLIS); } } private void goGuide() { SplashActivity.this.startActivity(new Intent(SplashActivity.this, GuidePagerActivity.class)); SplashActivity.this.finish(); } private void goHome() { SplashActivity.this.startActivity(new Intent(SplashActivity.this, MainActivity.class)); SplashActivity.this.finish(); } }

public class GuidePagerActivity extends Activity implements OnViewChangeListener {

    private GuideScollLayout guideScollLayout;
    private ImageView[] imageViews;
    private int count;
    private int currenItem;
    private ImageView enterAppImageView;
    private LinearLayout pointLLayout;
//SharePreferences表示
private static final String SHAREDPREFERENCES_FIRST_ENTER = "first_enter";
    private int curPos = 0;//記錄當前位置
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_guide_pager);
initView();
}

    private void initView() {
        guideScollLayout = (GuideScollLayout) findViewById(R.id.GuideScorllLayout_id);
enterAppImageView = (ImageView) findViewById(R.id.guide_pager_imageview_enterapp);
enterAppImageView.setOnClickListener(onClickListener);
count = guideScollLayout.getChildCount();
//把擁有子佈局圓點的父View初始化
pointLLayout = (LinearLayout) findViewById(R.id.llayout);
imageViews = new ImageView[count];
enterAppImageView.setImageAlpha(0);
//遍歷該父View,用getChildAt()得到其所有的子View
for (int i = 0; i < count; i++) {
            imageViews[i] = (ImageView) pointLLayout.getChildAt(i);
imageViews[i].setEnabled(true);
imageViews[i].setTag(i);
}
        currenItem = 0;
imageViews[currenItem].setEnabled(false);
//新增自定義好的划動方法的監聽
guideScollLayout.SetOnViewChangeListener(this);
}

    @Override
public void OnViewChange(int position) {
        setcurrenPoint(position);
}

    private View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
public void onClick(View v) {
            switch (v.getId()) {
                case R.id.guide_pager_imageview_enterapp:
                    setGuided();
goHome();
                    break;
}
        }
    };
//控制滾動UI顯示
private void setcurrenPoint(int position) {
        if (position < 0 || position > count - 1 || currenItem == position) {
            return;
}
        imageViews[currenItem].setEnabled(true);
imageViews[position].setEnabled(false);
currenItem = position;
Animation alphaim = new AlphaAnimation(0.1f, 1.0f);//設定漸變動畫,灰度從0.1~1.0
alphaim.setDuration(1000);//動畫持續1秒
        //設定伸縮動畫,從中心開始,從0.1伸展到1.0(原大少)
Animation scakeanim = new ScaleAnimation(0.1f, 1.0f, 0.1f, 1.0f, Animation.RELATIVE_TO_PARENT, 0.5f, Animation.RELATIVE_TO_PARENT, 0.0f);
scakeanim.setDuration(500);
        if (currenItem == 3) {//划動到最後一頁
enterAppImageView.setVisibility(View.VISIBLE);
enterAppImageView.startAnimation(alphaim);
enterAppImageView.startAnimation(scakeanim);
} else if (curPos != 3) {
            enterAppImageView.setVisibility(View.GONE);
}
        curPos = position;
}

    /**
     * 設定引導頁,下次開啟程式不再進入引導頁
     */
private void setGuided() {
        SharedPreferences sharedPreferences = GuidePagerActivity.this.getSharedPreferences(SHAREDPREFERENCES_FIRST_ENTER, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
//存入資料
editor.putBoolean("isFirstIn", false);
//提交修改
editor.commit();
}

    /**
     * 進入程式主介面
     */
private void goHome() {
        GuidePagerActivity.this.startActivity(new Intent(GuidePagerActivity.this, MainActivity.class));
}

}

這裡要講解一下,這專案裡的引導頁之所以不用viewpager去實現是因為想要自己設定頁面划動的數度,所以才自定義了一個ViewGroup。

程式碼如下:

private static final int SNAP_VELOCITY = 400;

接下來是主體的指引蒙板效果圖:


如圖,上面是三個步驟的UI,當然那些圖也要自己做或是自己找,關於這個專案用的資源也是從別的地方拿來湊合著用的,唯獨這個步驟是自己做的,希望被用到的原素材的擁有者別介意。上面的效果就達到了使用者與螢幕互動的意圖了,過去很多的指引步驟,在使用者面前顯示自己的app是如何使用的時候,很多都是使用一張圖去粗略帶過,使用者只能划動到達下一張,平且有些指引還不會讓使用者和真正的介面接觸互動,只通過一張加了特效的圖片來帶過,這樣是不太好的。如果是這個app的介紹的話在“引導頁”裡面做就好。


首先我們把資源引入到自己的專案裡面,讓後根據螢幕的大少和所需要顯示到的位置上,自己手動排列好,我這裡比較簡單,三個手勢引導都是在底部,所以根據自己專案的實際情況可能會出現更復雜的排列布局,這裡我就不多說了。排好而後只需要顯示第一個步驟就可以了。其他的步驟都設定為隱藏就可以了。程式碼是:android:visibility="gone"。而注意一下的是,裝載這些指引手勢的xml檔案,的最外層佈局不應該設定有圖片背景,因為它需要跟真正的主介面作一個位置對齊,要不然你排列擺好那些指引手勢的圖片是幹嘛呢?完成後我們再來看一下PopupWindow的程式碼吧。

部分程式碼:

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.guidestep_imageview_1:
            imageViewStep1.setVisibility(View.GONE);
imageViewStep1.setEnabled(false);
imageViewStep2.setVisibility(View.VISIBLE);
imageViewStep2.setEnabled(true);
            break;
        case R.id.guidestep_imageview_2:
            imageViewStep2.setVisibility(View.GONE);
imageViewStep2.setEnabled(false);
imageViewStep3.setVisibility(View.VISIBLE);
imageViewStep3.setEnabled(true);
            break;
        case R.id.guidestep_imageview_3:
            imageViewStep3.setVisibility(View.GONE);
imageViewStep3.setEnabled(false);
dismiss();
            break;
}
}

程式碼也異常的粗暴簡單,十分明瞭。邏輯也是腦殘的也能想到了,就是在點選了一個步驟的時候,在隱藏該步驟的圖片的時候同時也顯示出下一步,只要在程式碼引入這些空間的資源再加上對他們的監聽就可以做到了,是不是很簡單明瞭呢?

本次專案也用到了SharePerferences,由於不是重點,所以這裡就略過它的使用方法了有興趣的同學可以自己去查查。不過本專案中,因為方便大家觀看效果所以沒有對那些指引蒙板的步驟做SharePerferences的判斷,真正使用的時候你不肯能讓使用者每一次進入app的時候都要去點選指引蒙板的操作,而應該只是第一次進入app的主介面的時候才出現,過後用SharePerferences對其作記錄儲存,這樣才真正完成了指引蒙板的使用。

嘛,這次就到這裡,筆豬會繼續更的,謝謝能來看的人,希望對你們有所幫助。