实现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的方式来实现。有兴趣的朋友可以自己动手实现。
实现Android4.4系统设置分页滑动浏览功能的更多相关文章
- Android 使用ViewPager结合PhotoView开源组件实现网络图片在线浏览功能
在实际的开发中,我们市场会遇到这样的情况:点击某图片,浏览某列表(某列表详情)中的所有图片数据,当然,这些图片是可以放大和缩小的,比如我们看下百度贴吧的浏览大图的效果: 链接 这种功能,在一些app ...
- ViewPager取消左右滑动切换功能
ViewPager取消左右滑动切换功能 最近做项目要求某种情况下ViewPager不能滑动,那么我们只需要重写这个方法就可以禁止ViewPager滑动 IndexViewPager.java: imp ...
- Nginx 和 Apache 开启目录浏览功能
1.Nginx 在相应项目的 Server 段中的 location 段中,添加 autoindex on.例如: server { listen ; server_name www.dee.prac ...
- Swipe to back not working滑动后退功能消失?
如果你发现滑动后退功能突然失效了,很可能是因为你隐藏了NavigationBar 或者定制了 leftBarButtonItem(s) 这会导致 NavigationController 的 inte ...
- nginx和apache配置目录浏览功能
今天工作需要,要给客户提供一个patch的下载地址,于是想用nginx的目录浏览功能来做,需要让客户看到指定一个目录下的文件列表,然后让他自己来选择该下载那个文件: 我们都知道在apache下可以配置 ...
- ViewPager撤消左右滑动切换功能
ViewPager取消左右滑动切换功能 最近做项目要求某种情况下ViewPager不能滑动,那么我们只需要重写这个方法就可以禁止ViewPager滑动 IndexViewPager.java: imp ...
- iOS之手势滑动返回功能-b
iOS中如果不自定义UINavigationBar,通过手势向右滑是可以实现返回的,这时左边的标题文字提示的是上一个ViewController的标题,如果需要把文字改为简约风格,例如弄过箭头返回啥的 ...
- 禁用ios7 手势滑动返回功能
禁用ios7 手势滑动返回功能 版权声明:本文为博主原创文章,未经博主允许不得转载. 在有的时候,我们不需要手势返回功能,那么可以在页面中添加以下代码: - (void)viewDidAppear:( ...
- 自定义listView添加滑动删除功能
今天研究了一下android里面的手势,结合昨天学习的自定义View,做了一个自定义的listview,继承自listView,添加了条目的滑动手势操作,滑动后出现一个删除按钮,点击删除按钮,触发一个 ...
随机推荐
- Script循环语句 的相关知识跟练习
循环语句有两种问题类型:穷举和迭代 穷举: 在不知道什么情况下才是我们需要的结果的时候,只能让它一个一个的都执行一遍 迭代:在现有的条件下,根据规律,不断求解中间情况,最终推选出结果 两个关键词 br ...
- 批量运行R包
#批量运行包:all.pcg <- c("data.table","ggplot2","rmarkdown","tidyr& ...
- UVA10561 Treblecross 组合游戏/SG定理
Treblecross is a two player gamewhere the goal is to get three X in a row on a one-dimensional board ...
- 我的android学习经历33
在Activity中添加菜单 1.在res目录下新建文件夹menu 右击res,选择new->Folder,Folder name写为menu 2.在新建的menu目录下新建一个xml文件 右击 ...
- [Python正则表达式] 字符串中xml标签的匹配
现在有一个需求,比如给定如下数据: 0-0-0 0:0:0 #### the 68th annual golden globe awards #### the king s speech earns ...
- 前端工程师的PS默认工作区
右侧依次是信息.图层.历史记录,如下图:
- C语言语法之关键字
注:该内容整理自以下链接. http://www.cnblogs.com/yezhenhan/archive/2011/10/16/2214420.html 由ANSI标准定义的C语言关键字共32个: ...
- leetcode-188 买卖股票4
题目 给定一个数组表示股票每天的价格,最多交易k次,且手上最多只能拥有一支股票(即只能先卖出手上现有的股票再去购买新的股票),求最大的收益. 题目链接:买卖股票4 开始思路不清楚,参考 ...
- Spring Boot工程发布到Docker
先聊聊闲话 搞过企业级的application运维的同仁肯定深有感触,每个application的功能交叉错杂,数据交换就让人焦头烂额(当然这和顶层业务设计有关系), 几十个application发布 ...
- Unity ShaderLab学习总结
http://www.jianshu.com/p/7b9498e58659 Unity ShaderLab学习总结 Why Bothers? 为什么已经有ShaderForge这种可视化Shader编 ...