实现Android4.4系统设置分页滑动浏览功能

需求描述:

由于手机功能越来越完善,相应的偏好设置也就越来越多;从用户体验的角度考虑,为了让用户能够在短时间内对常用的偏好设置进行操作,如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的方式来实现。有兴趣的朋友可以自己动手实现。

时间: 2024-11-06 16:04:56

实现Android4.4系统设置分页滑动浏览功能的相关文章

购物网站讨论2:商品浏览功能实现

商品浏览功能界面图如下: 1.控制器代码.视图代码理解. 2.分页功能是如何实现的?

【javascript/css】Javascript+Css实现图片滑动浏览效果

今天用js+css来做一个能够左右滑动的图片浏览效果. 首先写一个结构,包括需要浏览的两张图,以及能够点击来滑动图片的两个按钮. 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5 <script type="text/javascrip

Android 实现用户列表信息滑动删除功能和选择删除功能

在项目开发过程中,常常需要对用户列表的信息进行删除的操作.Android中常用的删除操作方式有两种 ,一种就是类似微信的滑动出现删除按钮方式,还有一种是通过CheckBox进行选择,然后通过按钮进行删除的方式.本来的实例集成上述的两种操作方式来实现用户列表删除的效果. 设计思路:在适配器类MyAdapter一个滑动删除按钮显示或隐藏的Map,一个用于CheckBox是否选中的Map和一个与MainAcitivyt进行数据交互的接口ContentsDeleteListener,同时该接口包含两个方

滑动返回功能被覆盖的解决思路

在OC开发中,导航控制器是一个非常常见的控件,而且在不少使用时候,我们需要自定义导航条NavigationBar.但是这个做法可能带来一些小麻烦,下面是我遇到的问题以及解决方案的思维过程. 在苹果内部,返回功能的实现自带了一个边缘的滑动返回功能.但是一旦使用我们自定义的NavigationBar,子控制器这个功能便会消失.如果我们既要用到自定义,又要保留滑动返回功能,那我们首先要分析消失的原因,再来寻找解决方案. 既然替换NavigationBar会导致滑动返回功能的消失,那我们基本可以确定,在

【微信公众平台开发】借用微信内置图片浏览功能

开发微信公众平台时,碰到文章中有很多图片,需要可以点开图片浏览:那么点击图片直接调用微信客户端自带的图片播放组件会省很多事.否则你得去摆弄折腾各种图片浏览插件,比如photoswipe. 个人封装功能成一个js文件.把该文件放到你需要的网页里面即可,这样文章当你点击图片时,就会调用图片浏览功能! <script> function addLoadEvent(func){ //将函数作为参数,此函数就是 onload 触发时需要执行的某个函数 var oldonload=window.onloa

给文件右击菜单增加7-ZIP浏览功能(用注册表设置Shell调用预览命令)

疯狂delphi delphiXE7.XE8.XE10公开课A 群号:58592705 QQ:513187410 朱建强 BAT-给文件右击菜单增加7-ZIP浏览功能 Reg给文件右击菜单增加7-ZIP浏览功能 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\*\shell\用7-ZIP浏览(ZJQ)]"icon"="d:\\7ZIP.ico" [HKEY_CLASSES_ROOT\*\shell\用7

iOS之手势滑动返回功能-b

iOS中如果不自定义UINavigationBar,通过手势向右滑是可以实现返回的,这时左边的标题文字提示的是上一个ViewController的标题,如果需要把文字改为简约风格,例如弄过箭头返回啥的,那么你需要自定义UINavigationBar,但当你自定义navigationBar后,这个功能就会自动失效. 屏蔽右滑返回功能代码:   if ([self.navigationController respondsToSelector:@selector(interactivePopGest

nginx和apache配置目录浏览功能

今天工作需要,要给客户提供一个patch的下载地址,于是想用nginx的目录浏览功能来做,需要让客户看到指定一个目录下的文件列表,然后让他自己来选择该下载那个文件: 我们都知道在apache下可以配置访问web服务器的某个路径时,自动显示其目录下面的文件列表的,其实Nginx一点也不比apache弱,它当然也可以实现这个功能,而且还非常容易和简单:主要用到autoindex 这个参数来开启,其配置如下: 复制代码代码如下: location / {           root /data/ww

自定义listView添加滑动删除功能

今天研究了一下android里面的手势,结合昨天学习的自定义View,做了一个自定义的listview,继承自listView,添加了条目的滑动手势操作,滑动后出现一个删除按钮,点击删除按钮,触发一个删除的事件,在事件中进行删除当选行的元素,刷新listview. 一共分为以下几步进行: 1.新建一个按钮的布局文件,用来作为动态添加的按钮:layout_button.xml <?xml version="1.0" encoding="utf-8"?> &