zoukankan      html  css  js  c++  java
  • 实现Android4.4系统设置分页滑动浏览功能

    需求描写叙述:

        因为手机功能越来越完好,对应的偏好设置也就越来越多。从用户体验的角度考虑,为了让用户可以在短时间内对经常使用的偏好设置进行操作,如WIFI,蜂窝数据等。单独将一些经常使用的设置功能单独展示出来。已达到降低用户操作的可能性。因此採用将系统设置页面进行分页展示并可以滑动进行切换。

    效果图:

                  



        对于了解Settings源代码的同学应该知道,Settings的设计相对来说并非非常easy,大刀阔斧的对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,仅仅是加载的布局文件不同来达到需求。我已经验证过,这里为了让大家easy理解,便採用了复制Settings的方式来实现。有兴趣的朋友能够自己动手实现。



  • 相关阅读:
    python流程控制
    数据类型
    python之初接触
    使用 HttpWebRequest 向网站提交数据
    在 ASP.NET MVC4 中使用 NInject
    第一篇 微信商城 开发前的准备工作
    (一)模块基础
    函数之递归、匿名函数及内置方法
    装饰器的使用原理
    mybatis返回list
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/6932764.html
Copyright © 2011-2022 走看看