网易新闻这种滑动TAB效果,在android软件中还是比较常见的(是不是原创我不清楚,仅当学习研究之用~~~)。
比较常见的做法是:在FrameLayout里包装TAB bar,再在FrameLayout加一个虚拟的tab,切换tab时用虚拟tab在之前选中和当前选中的tab距离之间做一个移动动画。
用此种方法的十之八九,但在复杂的布局中FrameLayout不是你想加就能加滴,加了很容易崩溃滴^_^,此法的劣势大家明了吧?不明那就慢慢明吧。
今天我采用一种更加高效、灵活的方法来实现这种大家喜欢的花样--自画控件+Drawable动画。
大体原理跟FrameLayout加虚拟tab类似,以下是基本的实现方法:在切换tab时在之前选中的tab和当前选中的tab,做一个drawable移动动画。这个 drawable 就是当前选中tab的画面。
下面是我重载RadioGoup做的tab bar并实现了滑动效果的类
public class NewsRadioGroup extends RadioGroup implements OnCheckedChangeListener { private final Transformation mTransformation = new Transformation(); private Animation mAnimation; private OnCheckedChangeListener mOnCheckedChangeListener; private int mLastCheckedId = -1; private Drawable mDummy; private Drawable mDrawableNormal,mDrawableChecked; private boolean mAminDoing=false; public NewsRadioGroup(Context context) { super(context); init(); } public NewsRadioGroup(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { super.setOnCheckedChangeListener(this); mLastCheckedId = super.getCheckedRadioButtonId(); mDummy = getResources().getDrawable(R.drawable.rb_checked); mDrawableNormal = getResources().getDrawable(android.R.color.transparent); } public void onCheckedChanged(RadioGroup group, int checkedId) { if (mLastCheckedId != -1) { doAmin(checkedId); }else{ mLastCheckedId = checkedId; } if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener.onCheckedChanged(group, checkedId); } } private void doAmin( int checkedId){ RadioButton rbCurChecked = (RadioButton) super.findViewById(checkedId), rbLastChecked = (RadioButton) super.findViewById(mLastCheckedId); if(rbCurChecked==null||rbLastChecked==null){ mLastCheckedId=checkedId; return; } int X1=rbLastChecked.getLeft(),X2=rbCurChecked.getLeft(); if (X1 <= 0 && X2 <= 0) { mLastCheckedId=checkedId; return; } if (mDrawableChecked == null) { mDrawableChecked = rbCurChecked.getBackground(); mDummy.setBounds(0, 0, rbCurChecked.getWidth(), rbCurChecked.getHeight()); } rbCurChecked.setBackgroundDrawable(mDrawableNormal); if(mAminDoing && mAnimation!=null){ mAnimation.reset(); } mAnimation = new TranslateAnimation(X1,X2, rbCurChecked.getTop(), rbCurChecked.getTop()); mAnimation.setDuration(300); mAnimation.initialize(0, 0, 0, 0); mAminDoing=true; mAnimation.startNow(); invalidate(); } public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { mOnCheckedChangeListener = listener; } protected void onDraw(Canvas canvas) { if (mAnimation == null || !mAminDoing) { return; } if (!mAnimation.hasEnded()) { int sc = canvas.save(); mAnimation.getTransformation( AnimationUtils.currentAnimationTimeMillis(), mTransformation); canvas.concat(mTransformation.getMatrix()); mDummy.draw(canvas); canvas.restoreToCount(sc); invalidate(); } else { mAminDoing=false; setReallyCheck(); } } private void setReallyCheck() { if (mLastCheckedId != -1) { super.findViewById(mLastCheckedId).setBackgroundDrawable(mDrawableNormal); } mLastCheckedId = super.getCheckedRadioButtonId(); if (mLastCheckedId != -1) { super.findViewById(mLastCheckedId).setBackgroundDrawable(mDrawableChecked); } } }// end class NesRadioGroup
之前以为只要重写RadioGroup的check方法就可以拦截选中,没想到RadioGroup把实际的选中执行实现在setCheckxx里面,而这个函数是私有方法,最后绕了不小的圈子。
代码在上,具体的效果请见demo~~
转载至:http://aiwgame.com
在优亿开放日上,我们邀请过众多产品、运营方面的专家,但是工程师可能比较少一点,这次的活动,我们很高兴请到了百度地图高级研发工程师游东。游东具有四年以上的地图和导航开发经验,目前主要负责百度地图的SDK研发工作。在技术和开发上肯定是亲临第一线的高手。
我们整理了游东先生的演讲,希望给广大开发者提供实实在在的帮助。
一、百度地图介绍:高端手机实现陀螺仪导航
我们可以看到百度这一块对SDK重视还是比较大,我们的迭代版本速度也是比较快。一般来说一个小版本是一个月左右,如果大版本升级可能三个月左右的时间。iOS这边据我们统计,用户量不是特别大,所以iOS这块版本升级会慢一些。但是现在两个版本没有太大差异,基本功能完全一样。需要说明一点,大家现在有没有用到百度手机地图客户端,我们最新手机地铁可能是3G的时尚版本,我们SDK版本现在还是上个版本,在用户体验上还不太一致。不过,我们后面会有一些计划去增加版本的内容创新。
我们的支撑平台,可以看到是基于Android1.5最低版本,基本上所有Android设备都可以适配。可以看到我们SDK功能主要是提供地图浏览,包括实时交通,卫星图。自定义覆盖物,比如用户要添加一些自己独特的地标在地图上,比如合作伙伴去哪儿,在他们地图上就会加入酒店,检索周边有哪些酒店,就会标上当前价格,这些都可以用户自定义控制。
然后是一些基础搜索服务,比如POI,路线,地力,反地理编码之类。我们定位服务,精度如果Wi-Fi情况下200米左右,基站情况下500米以内。高端手机,基本上具备了陀螺仪,我刚刚来的时候在路上拿着手机导航过来,在走路的时候陀螺仪会标注你的方向,这样在行动过程中定位用户体验会非常好,基本上只需要通过基站就能够达到类似于GPS的精度用户体验感受。第五点就是一个离线地图。我刚刚说到现在SDK这个离线地图,跟我们百度地图手机客户端产品相比较,数据会旧一点,我们也会考虑进行升级。
二、设计思路:功能盖过谷歌
我们的设计思路,一个是功能完整。百度SDK跟Google相比较,我们的功能完全能够做到,对方有的我们都有,性能满足也会做一些性能方面测试。使用方便,我们的接口设计,还是有一点参考,相对于Google地图来说,或者相对于iOS来说,百度尽量考虑开发者便利性,如果从第三方图上API切换过来,接口尽量减少。百度在发布之前会做严格测试,比如24小时不间断使用,搜索上万个Case,有5万以上Monkey测试。在性能方面,跟手机地图产品保持一致,百度地图SDK内核跟百度产品内核是一致的,都是用同一套内核。
在应用型设计,可以看到我们设计的这几个API类,MapView都是GoogleAPI都有的。在搜索,我们都是基于接口调用立刻返回得到的结果。如果要使用百度开发的SDK,首先要到我们官网申请一个API Key,只需要填上你的名字。把我们SDK的两个包导入到对应位置,因为我们的内核可能是基于C++开发。在应用Manifest里面增加一些SDK使用权限,比如获得Wi-Fi的能力,就可以在这个里面进行展示地图内容。
这里说明一点,如果没有展示地图的需求,你也可以有我们的包,只需要使用检索接口,有可以获得检索内容,或者只用定位接口,也可以获得定位的内容,坐标,这不是强制的。你的HML里面配备MapView,我们有一个核心类,其他第三方没有,百度地图的所有功能都是基于这个BMapManager,这是一个官能管理类。BMapManager的使用放到onCreate就可以进行使用。这里有几个使用约定,我们SDK只基于主线程里使用,我们后续也会考虑改进。MapView是一个单实例,我们底图提供一些基础信息,比如道路街道,学校,公园,实时交通信息非常简单。
覆盖物是一个很重要的使用场景,大家会基于自己需求定制你的地图上的标注,根据我们提供现有类,比如这是你当前位置,不需要你自己做改动,我们自己已经添加一些资源在里面,就可以显示你当前位置和误差半径在里面,还有个路线公交查询,调用相关的Overlay,就可以把路线显示在地图上。可以看一下这个效果,这是MyLocationOverlay,显示的当前位置和路径半径。在使用的时候,你会注意到,可以设置传感器,如果有这个传感器,题愿意打开,这样在行动过程当中用户体验会更好一些。
转载至:炒股风暴 http://aiwgame.com
我们现在提供搜索服务,基本上是一些比较基础的服务在里面。现在,产品这边已经上了用户的详细信息数据,现在这块SDK暂时还没有加,后期还会有计划。在调用搜索接口的时候,可以看到比如要搜索肯德基,输入中间一个坐标,根据那个PoiOverlay坐标,搜索附近范围内就会有一个图标,如果搜索到结果就会通知你,你可以带这个接口里面进行处理,这样就可以显示地图上面,这个标注都是我们SDK提供好的,不需要你自己做设置,这是查询路线的。
搜索内部也只有一个实例,不能同时发起几个搜索。搜索可以支持多关键字,比如搜索多个类型,可以搜宾馆,也可以搜车站,会一次性反馈给你几个搜索,你加入的关键字可以在回调里面进行处理。当然,我们服务器里面有压力考虑,你保证最好反馈结果控制在50以内,你是所有结果,比如一个关键字就能返回10个,两个关键字,最好只设5个关键字,这样就可以返回50个,当然不能设太多,服务器在计算的时候会有一些压力,就会导致搜索失败的情况。
定位服务,定位是由网络,GPS,Wi-Fi,是一个混合定位,如果只有Wi-Fi也可以,也是通过注册回调里面获得结果。盖有一个地图包,我们提供官网地图,直接放到SD卡目录的BaiduMapSDK里面,你就不需要做太多扫描,第一次扫描之后会做一些文件修改,进行识别,到处的是正确地图。当然,有些用户会反馈,为什么扫描错误几次之后会错误,实际上已经扫描成功了。
我们的离线地图包也是可以支持多个应用共享,如果多个应用都用了SDK,只需要一个地图包就可以了。现在这块SDK计划,我们后期产品也正在开发过程当中,后期会支持P7的SDK。我们现在SDK有一些用户也会反馈,对于个别用户来说不是特别灵活,对于他们来说地图开发包体积太大,我们后面也会考虑尽量精简,或者做成一个可配置的灵活包,用户根据自己需求去配置他吸需要的一些功能,我们后期会支持地图矢量化,包括我们看到3D效果也会进行扩展。
当然,矢量地图量比较小,从我们现有掌握数据来说开发者并不太在意这块,我们产品这块数据量减少90%以上。我们AP资源可以到我们官网,微博上面关注,或者贴吧上面,我们也可以及时反馈。最后做一个广告,现在LBS还在招人,如果开发者有兴趣可以过来面试一下,还有机会成为同事,谢谢大家。
编辑对技术不是太懂,游工程师的讲解远远多于小编整理的,感兴趣的朋友可以在这里下载完整的PPT;喜欢百度地图的朋友请点击这里,或者加微博。
转载至:炒股风暴 http://aiwgame.com
delegate 设置协议 BOOL directionalLockEnabled 指定控件是否只能在一个方向上滚动 BOOL bounces 控制控件遇到边框是否反弹 BOOL alwaysBounceVertical 控制垂直方向遇到边框是否反弹 BOOL alwaysBounceHorizontal 控制水平方向遇到边框是否反弹 BOOL pagingEnabled 控制控件是否整页翻动 BOOL scrollEnabled 控制控件是否能滚动 BOOL showsHorizontalScrollIndicator 控制是否显示水平方向的滚动条 BOOL
showsVerticalScrollIndicator 控制是否显示垂直方向的滚动条 UIEdgeInsets scrollIndicatorInsets 指定滚动条在scrollerView中的位置 UIScrollViewIndicatorStyle
indicatorStyle 设定滚动条的样式 float decelerationRate 改变scrollerView的减速点位置 BOOL tracking 监控当前目标是否正在被跟踪 BOOL dragging 监控当前目标是否正在被拖拽 BOOL decelerating 监控当前目标是否正在减速 BOOL delaysContentTouches 控制视图是否延时调用开始滚动的方法 BOOL canCancelContentTouches 控制控件是否接触取消touch的事件 float minimumZoomScale 缩小的最小比例 float maximumZoomScale 放大的最大比例 float zoomScale 设置变化比例 BOOL bouncesZoom 控制缩放的时候是否会反弹 BOOL zooming 判断控件的大小是否正在改变 BOOL zoomBouncing 判断是否正在进行缩放反弹 BOOL scrollsToTop 控制控件滚动到顶部
这里把UIScrollView的几个要点总结下:
从你的手指touch屏幕开始,scrollView开始一个timer,如果:
1. 150ms内如果你的手指没有任何动作,消息就会传给subView。
2. 150ms内手指有明显的滑动(一个swipe动作),scrollView就会滚动,消息不会传给subView,这里就是产生问题二的原因。
3. 150ms内手指没有滑动,scrollView将消息传给subView,但是之后手指开始滑动,scrollView传送touchesCancelled消息给subView,然后开始滚动。
观察下tableView的情况,你先按住一个cell,cell开始高亮,手不要放开,开始滑动,tableView开始滚动,高亮取消。
delaysContentTouches的作用:
这个标志默认是YES,使用上面的150ms的timer,如果设置为NO,touch事件立即传递给subView,不会有150ms的等待。
cancelsTouches的作用:
这个标准默认为YES,如果设置为NO,这消息一旦传递给subView,这scroll事件不会再发生。