實現Android4.4系統設定分頁滑動瀏覽功能

來源:互聯網
上載者:User

標籤:android   style   blog   http   color   io   os   使用   ar   

需求描述:

    由於手機功能越來越完善,相應的喜好設定也就越來越多;從使用者體驗的角度考慮,為了讓使用者能夠在短時間內對常用的喜好設定進行操作,如WIFI,蜂窩資料等。單獨將一些常用的設定功能單獨展示出來,已達到減少使用者操作的可能性。因此採用將系統設定頁面進行分頁展示並可以滑動進行切換。

              



    對於瞭解Settings源碼的同學應該知道,Settings的設計相對來說並不是很簡單,大刀闊斧的對Settings可能會引起更多的bug。因此若實現該需求則在保持原有Settings功能完整的情況下進行低耦合高內聚的修改。

    由於Settings是一個Activity,因此,我這裡採用ViewPager結合Activity的方法實現該功能。也就是說把Settings作為一個子View嵌入到ViewPager中,同時複製一個新的Settings為OffenUsedSettings作為另一個字View,該OffenUsedSettings採用與Settings相同的設計思路進行,或者可以完全的複製,只是在載入布局的時候加以改變。具體架構設計如:


這裡貼出SettingsActivity.java全部代碼和OffenUsedActivity.java關鍵區段代碼,其他部分與原有Settings相同。

SettingsActivity.java代碼:


package com.android.settings;


import java.util.ArrayList;


import android.app.Activity;
import android.app.LocalActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.Window;
import android.widget.CompoundButton;
import android.widget.RadioGroup;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;


public class SettingsActivity extends Activity implements OnCheckedChangeListener, OnPageChangeListener {
    private RadioGroup mRadioGroup;
    private RadioButton mOffenUsed, mAll;
    private ViewPager mViewPager;
    private Context mContext;
    private LocalActivityManager mManager;
    private SettingsAdapter mAdapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_settings);
        mContext = SettingsActivity.this;
        mManager = new LocalActivityManager(this, false);
        mManager.dispatchCreate(savedInstanceState);
        initView();
    }


    @Override
    protected void onResume() {
        super.onResume();
        mManager.dispatchResume();
        if (mViewPager != null) {
            switch (mViewPager.getCurrentItem()) {
            case 0:
                Activity offenUsedActivity = mManager.getActivity("OFFENUSED");
                if (offenUsedActivity != null && offenUsedActivity instanceof OffenUsedSettings) {
                    ((OffenUsedSettings) offenUsedActivity).invisibleOnScreen();
                }
                break;
            case 1:
                Activity allActivity = mManager.getActivity("ALL");
                if (allActivity != null && allActivity instanceof Settings) {
                    ((Settings) allActivity).invisibleOnScreen();
                }
                break;
            }
        }
    }

    private void initView() {
        mRadioGroup = (RadioGroup) findViewById(R.id.rg_settings);
        mOffenUsed = (RadioButton) findViewById(R.id.rb_offen_used);
        mOffenUsed.setOnCheckedChangeListener(this);
        mAll = (RadioButton) findViewById(R.id.rb_all);
        mAll.setOnCheckedChangeListener(this);
        mViewPager = (ViewPager) findViewById(R.id.vp_settings);
        mViewPager.setOnPageChangeListener(this);


        final ArrayList<View> list = new ArrayList<View>();
        Intent intentCommon = new Intent(mContext, OffenUsedSettings.class);
        list.add(getView("OFFENUSED", intentCommon));
        Intent intentMain = new Intent(mContext, Settings.class);
        list.add(getView("ALL", intentMain));


        mAdapter = new SettingsAdapter(mContext, list);
        mViewPager.setAdapter(mAdapter);


        if (mOffenUsed.isChecked()) {
            mViewPager.setCurrentItem(0);
            mRadioGroup.setBackgroundResource(R.drawable.settings_common);
        } else if (mAll.isChecked()) {
            mViewPager.setCurrentItem(1);
            mRadioGroup.setBackgroundResource(R.drawable.settings_main);
        }
    }


    private View getView(String id, Intent intent) {
        return mManager.startActivity(id, intent).getDecorView();
    }


    @Override
    public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
        if (arg1) {
            switch (arg0.getId()) {
            case R.id.rb_offen_used:
                mViewPager.setCurrentItem(0);
                Activity offenUsedActivity = mManager.getActivity("OFFENUSED");
                if (offenUsedActivity != null && offenUsedActivity instanceof OffenUsedSettings) {
                    ((OffenUsedSettings) offenUsedActivity).invisibleOnScreen();
                }
                break;


            case R.id.rb_all:
                mViewPager.setCurrentItem(1);
                Activity allActivity = mManager.getActivity("ALL");
                if (allActivity != null && allActivity instanceof Settings) {
                    ((Settings) allActivity).invisibleOnScreen();
                }
                break;
            }
        }
    }


    @Override
    public void onPageScrollStateChanged(int arg0) {
    }


    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
    }


    @Override
    public void onPageSelected(int arg0) {
        switch (arg0) {
        case 0:
            if (!mOffenUsed.isChecked())
                mOffenUsed.setChecked(true);
            mRadioGroup.setBackgroundResource(R.drawable.settings_common);
            break;
        case 1:
            if (!mAll.isChecked())
                mAll.setChecked(true);
            mRadioGroup.setBackgroundResource(R.drawable.settings_main);
            break;
        }
    }
}


這裡主要對上面代碼中藍色和紅色部分進行簡單描述,其他都是很基礎的部分我相信這裡不需要我在贅述。

紅色代碼部分主要將當前Activity作為一個容器以便於可以將其他的Activity作為子View嵌入其中。需要注意的是第二個參數,源碼中給出的解釋是@param singleMode Ture if the LocalActivityManager should keep a maximum of one activity resume.我這裡理解的大概的意思再建立子Activity的時候是否執行所有子Activity的onResume的方法,如果為true,則只執行ViewPager中最後一個建立的Activity的onResume()方法。(這種結論也得到了證實,如果這裡為true,則ViewPager中只有最後一個子Activity中的onResume()方法被調用)因此這裡我們給出的實參是false。

藍色部分代碼的原因是,ViewPager+Activity的方式會導致子Activity中生命週期函數的紊亂,當然在第一次建立子Activity的時候onResume()方法會正常執行,但是當我們建立成功後,按home鍵將應用程式切換到背景時候,在切換回活動狀態的時候子Activity的onResume()方法並不會正確調用,但是最外層中的Activity,也就是這裡的SettingsActivity方法中的onRuesme()方法會正常被調用,因此這部分代碼可以解決這個問題。

OffenUsedSettings.java


    /**
     * Populate the activity with the top-level headers.
     */
    @Override
    public void onBuildHeaders(List<Header> headers) {
        if (!onIsHidingHeaders()) {
            PDebug.Start("loadHeadersFromResource");
 
loadHeadersFromResource(R.xml.offen_used_settings_headers, headers);

            PDebug.End("loadHeadersFromResource");
            updateHeaderList(headers);
        }
    }


以上紫色代碼中主要是在載入不同的布局檔案。其他與原有的Settings無異。

因此代碼解釋到這裡已經節本完成了,那麼值得再叨叨的是,既然OffenusedSettings.java中只是修改以實現載入不同的布局檔案來達到前文敘述的需求,為什麼不同時使用兩個Settings作為子Activity呢?

答案是可定的。我們完全可以把兩個Settings同時作為子Activity,只是載入的布局檔案不同來達到需求。我已經驗證過,這裡為了讓大家容易理解,便採用了複製Settings的方式來實現。有興趣的朋友可以自己動手實現。



實現Android4.4系統設定分頁滑動瀏覽功能

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.