Android-自定义多TAB悬浮控件实现蘑菇街首页效果
因为项目的一些需求需要用到此种展现方式. 找了市面上大部分有类似功能的应用. 基本思路嵌套ScrollView 转换事件分发给listview 实现. 但是此种方案有个缺点.
在ScrollView切换给Listview 事件的时候. 会卡顿. 体验效果并不好. 应用此方案的应用: 蘑菇街. 口袋夺宝 . 蘑菇街在快速滑动时才会卡顿. 优化处理过.
在找DEMO过程中. 发现此控件的方案更少. 仅有的几个问题颇多. 例如listview 长度不一时,切换VIewpager会造成大片空白. 需要重绘viewpager界面,
但是即使重绘了. 在Viewpager左右滑切换过程中. 会造成闪屏现象. 于是只能自己重写开始.
---------------------------下班时间到--------------回家再更新.
于是想了2种方案.
方案一: listview实现,
此方案实现相比之下较简单,不需要处理太多繁杂的地方. 但是有个致命缺点. 由于listview无法直接获取到滑动距离. 只能通过计算item高度来间接获取. 而当手势快速滑动时, 会产生惯性滑动,而惯性滑动是无法正确的
获取到滑动的高度的, 且滑动效果并不流畅. 于是此方案放弃.
方案二: scrollview 嵌套listview实现.
此Demo就采用了这种写法. 至于为什么要用Scrollview嵌套? 因为Scrollview 能准确的获得滑动的高度. 实现滑动切换非常流畅. 并且不需要重写事件分发.
就不会有了卡顿现象;
此方案并非是在整体界面中用Scrollview 嵌套所有布局. 而是在Viewpager的item里面 ScrollView嵌套listview;
难点: 整个控件的难点就在于 公共区域头部的处理. 悬浮窗反而是最简单的. (题外话: 主要目的就是为了写悬浮窗效果, 结果反而最简单. 蛋疼有木有!!!(╮(╯▽╰)╭ )
另外一个难点就在于Viewpager切换时的状态保存了. 此段比较绕. 我也是绕了好久才绕明白了.
最后: 由于是测试Demo 代码杂乱. 勿怪. 这几天将会抽取成库, 另外加上下拉刷新及加载更多功能. 希望能帮到有用的同学们把.
Demo周一附上(忘记上传网盘了.在公司电脑(。_°☆ ╲(- –)
-------------------------------------------------2015.11.27分割线-----------------------------------
好吧. 终于有空更新了. 目前已封装完毕 增加了下拉刷新功能; 核心方法变动较大, 由于常规的Scrollview嵌套listview 会让listview的复用消失. 于是使用交替事件实现.
核心代码
通过滑动的距离来 控制事件拦截 进行Scrollview和listview的交替执行
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
LogUtils.w("滑动距离------" + t);
ScrollY = t;
CheckMargin(t);
if (t >= offsetHeight - 2) {//上啦过程
mSupListView.setVisibility(View.VISIBLE);
if (t >= offsetHeight - 2) {
Constant.RET = false; //不拦截
} else {
Constant.RET = true; //拦截
}
} else {
mSupListView.setVisibility(View.GONE);
Constant.RET = true; //拦截
}
super.onScrollChanged(l, t, oldl, oldt);
}
配合拦截
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mHorizontalListView.getTop() > 0 && mHorizontalListView.getTop() <= Constant.offsetHeight - 2) {
Constant.RET = super.onInterceptTouchEvent(ev);
}
LogUtils.w("super.onInterceptTouchEvent(ev)=" + super.onInterceptTouchEvent(ev)); return Constant.RET && mGestureDetector.onTouchEvent(ev);
}
//此方法为判断是否是左右滑动 处理Viewpager事件拦截 从而不需要再自定义一个Viewpager进行事件判断
private class YScrollDetector extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
if (Math.abs(distanceY) >= Math.abs(distanceX)) {
return true; //如果更相对于左右滑动 事件交给子控件处理.
}
return false;
}
}
如何调用
@Override
public View createSuccessView() {
View view = View.inflate(getContext(), R.layout.home_fragment_context, null);
mScrollContainer = (LinearLayout) view.findViewById(R.id.scrollview_container);
mLinearLayout = (LinearLayout) view.findViewById(R.id.home_banner_header);//广告头的总布局;
mViewPager = (FragmentViewPager) view.findViewById(R.id.home_viewpager);
mHorizontalListView = (HorizontalListView) view.findViewById(R.id.user); //非悬浮导航
mSupListView = (HorizontalListView) view.findViewById(R.id.Sup); //悬浮导航
Constant.MY_INDICATOR = mSupListView;
imageView = (ImageView) view.findViewById(R.id.myimage);
mHorizontalListView.setAdapter(new OrderAdapter(getContext()));
mSupListView.setAdapter(new OrderAdapter(getContext()));
RefreshHeadView = (LinearLayout) view.findViewById(R.id.scrollView_refresh_head);
mSuspendScrollView = (SuspendScrollView) view.findViewById(R.id.home_scrollview);
//接受参数
mSuspendScrollView.setView(mLinearLayout, mSupListView, RefreshHeadView, mHorizontalListView,mScrollContainer);
mSuspendScrollView.setOnRefreshScrollViewListener(new SuspendScrollView.OnRefreshScrollViewListener() {
@Override
public void onRefresh() {
UiUtils.showToast("下啦刷新中");
//请求数据操作 子线程操作
ThreadManager.getInstance().createLongPool().execute(new Runnable() {
@Override
public void run() {
SystemClock.sleep(1000);//模拟请求数据
mSuspendScrollView.completeRefresh(); }
});
} /**
* 刷新完成时需要的操作 更新UI等
*/
@Override
public void onRefreshFinish() {
UiUtils.showToast("刷新完成");
}
});
mViewPager.setAdapter(new HomeFragmentViewPagerAdapter(getActivity().getSupportFragmentManager()));
mViewPager.setOffscreenPageLimit(2);//设置预加载 防止切换时状态丢失
setViewpagerHeight(mViewPager);
initIndicator();
return view;
}
Scrollview 所需要接收的参数:
/**
* 头部初始化
*
* @param banner 广告头
* @param sup 悬浮的头布局
* @param refreshHeadView 下啦刷新头布局
* @param NoSup 不是悬浮的布局
* @param mScrollContainer
*/
public void setView(View banner, HorizontalListView sup, LinearLayout refreshHeadView, HorizontalListView NoSup, LinearLayout mScrollContainer) { }
优化了很多细节上的处理 , 此Demo 应该是最终版了. 更贴近项目~.
http://pan.baidu.com/s/1bn2tlIf 地址.
注: 转载注明出处. 谢谢各位!
-------------------------------------------------------------2015.12.1更新------------------------------
修复转交事件卡顿BUG.

Android-自定义多TAB悬浮控件实现蘑菇街首页效果的更多相关文章
- android - 自定义(组合)控件 + 自定义控件外观
转载:http://www.cnblogs.com/bill-joy/archive/2012/04/26/2471831.html android - 自定义(组合)控件 + 自定义控件外观 A ...
- Android自定义模糊匹配搜索控件(二)
在项目中遇到一个需要通过某个字的值筛选匹配带出其他信息的需求,在这里将实现思路整理出来. 源码地址:https://github.com/whieenz/SearchSelect 先看效果图 上图中的 ...
- Android自定义PopupWindow显示在控件上方或者下方
记录学习之用 View view = mInflater.inflate(R.layout.layout_popupwindow, null); PopUpwindowLayout popUpwind ...
- Android 应用内悬浮控件实践总结
在工作中遇到一个需求,需要在整个应用的上层悬浮显示控件,目标效果如下图: 首先想到的是申请悬浮窗权限,OK~ 打开搜索引擎,映入眼帘的并不是如何申请,而是“Android 悬浮窗权限各机型各系统适配大 ...
- Android创建自定义的布局和控件
Android的自带布局有framelayout.linerlayout.relativelayout,外加两个百分比布局,但是这些无法灵活的满足我们的需要,所以我们要自己自定义并引入自己的布局.首先 ...
- Android开源的精美日历控件,热插拔设计的万能自定义UI
Android开源的精美日历控件,热插拔设计的万能自定义UI UI框架应该逻辑与界面实现分离,该日历控件使用了热插拔的设计 ,简单几步即可实现你需要的UI效果,热插拔的思想是你提供你的实现,我提供我的 ...
- Android UI开发之开源控件项目整理
一.Banner 1.https://github.com/youth5201314/banner Android广告图片轮播控件,支持无限循环和多种主题,可以灵活设置轮播样式.动画.轮播和切换时间. ...
- 获取 AlertDialog自定义的布局 的控件
AlertDialog自定义的布局 效果图: 创建dialog方法的代码如下: 1 LayoutInflater inflater = getLayoutInflater(); 2 View layo ...
- Android 开源组件 ----- Android LoopView无限自动轮转控件
Android 开源组件 ----- Android LoopView无限自动轮转控件 2015-12-28 15:26 by 杰瑞教育, 32 阅读, 0 评论, 收藏, 编辑 一.组件介绍 App ...
随机推荐
- 一个短路求值引起的一个小bug
今天在写一个判断字符串是否回文时因为短路求值问题导致了一个bug,记录如下: 代码如下 bool isPal(char str[],int len) { int begin=0; int end=le ...
- R文件相关(坑)
大家来找茬...为什么会出现红字,不能正确引用R文件管理的资源呢? 罪魁祸首就是那个import android.R(我根据IDE提示而自作聪明引用的) 删除那行以后,就不会红字了. 刚开始是拷贝了图 ...
- Android 设置隐式意图
AndroidManifest.xml对于被调用的activity: <activity android:name="com.wuyou.twoactivity.OtherActivi ...
- mysql主从配置(清晰的思路)
mysql主从配置.鄙人是在如下环境测试的: 主数据库所在的操作系统:win7 主数据库的版本:5.0 主数据库的ip地址:192.168.1.111 从数据库所在的操作系统:linux 从数据的版本 ...
- CABAC
CABAC(Context-based Adaptive Binary Arithmetic Coding),基于上下文的自适应二进制算术编码.CABAC是H.264/AVC标准中两种熵编码中的一种, ...
- 3.2 java中堆栈(stack)和堆(heap)(还在问静态变量放哪里,局部变量放哪里,静态区在哪里.....进来)
(1)内存分配的策略 按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的. 静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编 译时就可以给 ...
- Haskell函数的语法
本章讲的就是 Haskell 那套独特的语法结构,先从模式匹配开始.模式匹配通过检查数据的特定结构来检查其是否匹配,并按模式从中取得数据. 在定义函数时,你可以为不同的模式分别定义函数本身,这就让代码 ...
- poj 3710 Christmas Game(树上的删边游戏)
Christmas Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 1967 Accepted: 613 Des ...
- [转载]css hack
做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我们会极不情愿的使用这个不太友好的方式来达到大家要求的页面表现.我个人是不太推荐使用hack的,要知道 ...
- Shell上传文件到ftp
写一个shell文件,将给定的文件上传到指定的ftp. 代码如下: #!/bin/bash #用来将文件上传到ftp,输入参数:文件名(包括路径).ftp的IP.ftp的端口.用户名.密码 ip=$ ...