- 浏览: 5778701 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (890)
- WindowsPhone (0)
- android (88)
- android快速迭代 (17)
- android基础 (34)
- android进阶 (172)
- android高级 (0)
- android拾遗 (85)
- android动画&效果 (68)
- Material Design (13)
- LUA (5)
- j2me (32)
- jQuery (39)
- spring (26)
- hibernate (20)
- struts (26)
- tomcat (9)
- javascript+css+html (62)
- jsp+servlet+javabean (14)
- java (37)
- velocity+FCKeditor (13)
- linux+批处理 (9)
- mysql (19)
- MyEclipse (9)
- ajax (7)
- wap (8)
- j2ee+apache (24)
- 其他 (13)
- phonegap (35)
最新评论
-
Memories_NC:
本地lua脚本终于执行成功了,虽然不是通过redis
java中调用lua脚本语言1 -
ZHOU452840622:
大神://处理返回的接收状态 这个好像没有监听到 遇 ...
android 发送短信的两种方式 -
PXY:
拦截部分地址,怎么写的for(int i=0;i<lis ...
判断是否登录的拦截器SessionFilter -
maotou1988:
Android控件之带清空按钮(功能)的AutoComplet ...
自定义AutoCompleteTextView -
yangmaolinpl:
希望有表例子更好。。。,不过也看明白了。
浅谈onInterceptTouchEvent、onTouchEvent与onTouch
网上有一个StickyScrollView,称之为粘性ScrollView,比如一个垂直方向的布局,依次摆放几个子View,当某一个子View滚到到顶端时候要停靠在顶部,悬停在顶部的位置不动。这很像联系人的pinned,假设联系人按照Z分组后,若滚动到顶部,Z就悬停靠在顶端不动,下面到的联系人继续滚到。当用户下拉时候,又恢复正常。
StickyScrollView原先是继承自ScrollView,然而现在ScrollView已经被新型的NestedScrollView逐渐取代了,现在我把它改写成继承自NestedScrollView后,整理出来:
同时需要在res/values/attr.xml加入定义的属性:
使用起来很简单,在xml布局中把某一个子View增加一个属性:
即可实现该子View在NestedScrollView中,当滚动到顶部后悬停挂靠在顶部不动,直到下一个粘性子View滚动上来把它顶飞,或者用户下拉,拉出上面的View。如xml代码:
ViewPager与NestedScrollView套嵌会引起冲突,滑动不了的问题
https://blog.csdn.net/wjr1949/article/details/72479583?utm_source=itdadao&utm_medium=referral
StickyScrollView原先是继承自ScrollView,然而现在ScrollView已经被新型的NestedScrollView逐渐取代了,现在我把它改写成继承自NestedScrollView后,整理出来:
package zhangphil.test; import java.util.ArrayList; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.v4.widget.NestedScrollView; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; public class StickyScrollView extends NestedScrollView { /** * Tag for views that should stick and have constant drawing. e.g. TextViews, ImageViews etc */ public static final String STICKY_TAG = "sticky"; /** * Flag for views that should stick and have non-constant drawing. e.g. Buttons, ProgressBars etc */ public static final String FLAG_NONCONSTANT = "-nonconstant"; /** * Flag for views that have aren't fully opaque */ public static final String FLAG_HASTRANSPARANCY = "-hastransparancy"; /** * Default height of the shadow peeking out below the stuck view. */ private static final int DEFAULT_SHADOW_HEIGHT = 10; // dp; private ArrayList<View> stickyViews; private View currentlyStickingView; private float stickyViewTopOffset; private int stickyViewLeftOffset; private boolean redirectTouchesToStickyView; private boolean clippingToPadding; private boolean clipToPaddingHasBeenSet; private int mShadowHeight; private Drawable mShadowDrawable; private final Runnable invalidateRunnable = new Runnable() { @Override public void run() { if (currentlyStickingView != null) { int l = getLeftForViewRelativeOnlyChild(currentlyStickingView); int t = getBottomForViewRelativeOnlyChild(currentlyStickingView); int r = getRightForViewRelativeOnlyChild(currentlyStickingView); int b = (int) (getScrollY() + (currentlyStickingView.getHeight() + stickyViewTopOffset)); invalidate(l, t, r, b); } postDelayed(this, 16); } }; public StickyScrollView(Context context) { this(context, null); } public StickyScrollView(Context context, AttributeSet attrs) { this(context, attrs, android.R.attr.scrollViewStyle); } public StickyScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setup(); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StickyScrollView, defStyle, 0); final float density = context.getResources().getDisplayMetrics().density; int defaultShadowHeightInPix = (int) (DEFAULT_SHADOW_HEIGHT * density + 0.5f); mShadowHeight = a.getDimensionPixelSize( R.styleable.StickyScrollView_stuckShadowHeight, defaultShadowHeightInPix); int shadowDrawableRes = a.getResourceId( R.styleable.StickyScrollView_stuckShadowDrawable, -1); if (shadowDrawableRes != -1) { mShadowDrawable = context.getResources().getDrawable( shadowDrawableRes); } a.recycle(); } /** * Sets the height of the shadow drawable in pixels. * * @param height */ public void setShadowHeight(int height) { mShadowHeight = height; } public void setup() { stickyViews = new ArrayList<View>(); } private int getLeftForViewRelativeOnlyChild(View v) { int left = v.getLeft(); while (v.getParent() != getChildAt(0)) { v = (View) v.getParent(); left += v.getLeft(); } return left; } private int getTopForViewRelativeOnlyChild(View v) { int top = v.getTop(); while (v.getParent() != getChildAt(0)) { v = (View) v.getParent(); top += v.getTop(); } return top; } private int getRightForViewRelativeOnlyChild(View v) { int right = v.getRight(); while (v.getParent() != getChildAt(0)) { v = (View) v.getParent(); right += v.getRight(); } return right; } private int getBottomForViewRelativeOnlyChild(View v) { int bottom = v.getBottom(); while (v.getParent() != getChildAt(0)) { v = (View) v.getParent(); bottom += v.getBottom(); } return bottom; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (!clipToPaddingHasBeenSet) { clippingToPadding = true; } notifyHierarchyChanged(); } @Override public void setClipToPadding(boolean clipToPadding) { super.setClipToPadding(clipToPadding); clippingToPadding = clipToPadding; clipToPaddingHasBeenSet = true; } @Override public void addView(View child) { super.addView(child); findStickyViews(child); } @Override public void addView(View child, int index) { super.addView(child, index); findStickyViews(child); } @Override public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) { super.addView(child, index, params); findStickyViews(child); } @Override public void addView(View child, int width, int height) { super.addView(child, width, height); findStickyViews(child); } @Override public void addView(View child, android.view.ViewGroup.LayoutParams params) { super.addView(child, params); findStickyViews(child); } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); if (currentlyStickingView != null) { canvas.save(); canvas.translate(getPaddingLeft() + stickyViewLeftOffset, getScrollY() + stickyViewTopOffset + (clippingToPadding ? getPaddingTop() : 0)); canvas.clipRect(0, (clippingToPadding ? -stickyViewTopOffset : 0), getWidth() - stickyViewLeftOffset, currentlyStickingView.getHeight() + mShadowHeight + 1); if (mShadowDrawable != null) { int left = 0; int right = currentlyStickingView.getWidth(); int top = currentlyStickingView.getHeight(); int bottom = currentlyStickingView.getHeight() + mShadowHeight; mShadowDrawable.setBounds(left, top, right, bottom); mShadowDrawable.draw(canvas); } canvas.clipRect(0, (clippingToPadding ? -stickyViewTopOffset : 0), getWidth(), currentlyStickingView.getHeight()); if (getStringTagForView(currentlyStickingView).contains(FLAG_HASTRANSPARANCY)) { showView(currentlyStickingView); currentlyStickingView.draw(canvas); hideView(currentlyStickingView); } else { currentlyStickingView.draw(canvas); } canvas.restore(); } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { redirectTouchesToStickyView = true; } if (redirectTouchesToStickyView) { redirectTouchesToStickyView = currentlyStickingView != null; if (redirectTouchesToStickyView) { redirectTouchesToStickyView = ev.getY() <= (currentlyStickingView.getHeight() + stickyViewTopOffset) && ev.getX() >= getLeftForViewRelativeOnlyChild(currentlyStickingView) && ev.getX() <= getRightForViewRelativeOnlyChild(currentlyStickingView); } } else if (currentlyStickingView == null) { redirectTouchesToStickyView = false; } if (redirectTouchesToStickyView) { ev.offsetLocation(0, -1 * ((getScrollY() + stickyViewTopOffset) - getTopForViewRelativeOnlyChild(currentlyStickingView))); } return super.dispatchTouchEvent(ev); } private boolean hasNotDoneActionDown = true; @Override public boolean onTouchEvent(MotionEvent ev) { if (redirectTouchesToStickyView) { ev.offsetLocation(0, ((getScrollY() + stickyViewTopOffset) - getTopForViewRelativeOnlyChild(currentlyStickingView))); } if (ev.getAction() == MotionEvent.ACTION_DOWN) { hasNotDoneActionDown = false; } if (hasNotDoneActionDown) { MotionEvent down = MotionEvent.obtain(ev); down.setAction(MotionEvent.ACTION_DOWN); super.onTouchEvent(down); hasNotDoneActionDown = false; } if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { hasNotDoneActionDown = true; } return super.onTouchEvent(ev); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); doTheStickyThing(); } private void doTheStickyThing() { View viewThatShouldStick = null; View approachingView = null; for (View v : stickyViews) { int viewTop = getTopForViewRelativeOnlyChild(v) - getScrollY() + (clippingToPadding ? 0 : getPaddingTop()); if (viewTop <= 0) { if (viewThatShouldStick == null || viewTop > (getTopForViewRelativeOnlyChild(viewThatShouldStick) - getScrollY() + (clippingToPadding ? 0 : getPaddingTop()))) { viewThatShouldStick = v; } } else { if (approachingView == null || viewTop < (getTopForViewRelativeOnlyChild(approachingView) - getScrollY() + (clippingToPadding ? 0 : getPaddingTop()))) { approachingView = v; } } } if (viewThatShouldStick != null) { stickyViewTopOffset = approachingView == null ? 0 : Math.min(0, getTopForViewRelativeOnlyChild(approachingView) - getScrollY() + (clippingToPadding ? 0 : getPaddingTop()) - viewThatShouldStick.getHeight()); if (viewThatShouldStick != currentlyStickingView) { if (currentlyStickingView != null) { stopStickingCurrentlyStickingView(); } // only compute the left offset when we start sticking. stickyViewLeftOffset = getLeftForViewRelativeOnlyChild(viewThatShouldStick); startStickingView(viewThatShouldStick); } } else if (currentlyStickingView != null) { stopStickingCurrentlyStickingView(); } } private void startStickingView(View viewThatShouldStick) { currentlyStickingView = viewThatShouldStick; if (getStringTagForView(currentlyStickingView).contains(FLAG_HASTRANSPARANCY)) { hideView(currentlyStickingView); } if (((String) currentlyStickingView.getTag()).contains(FLAG_NONCONSTANT)) { post(invalidateRunnable); } } private void stopStickingCurrentlyStickingView() { if (getStringTagForView(currentlyStickingView).contains(FLAG_HASTRANSPARANCY)) { showView(currentlyStickingView); } currentlyStickingView = null; removeCallbacks(invalidateRunnable); } /** * Notify that the sticky attribute has been added or removed from one or more views in the View hierarchy */ public void notifyStickyAttributeChanged() { notifyHierarchyChanged(); } private void notifyHierarchyChanged() { if (currentlyStickingView != null) { stopStickingCurrentlyStickingView(); } stickyViews.clear(); findStickyViews(getChildAt(0)); doTheStickyThing(); invalidate(); } private void findStickyViews(View v) { if (v instanceof ViewGroup) { ViewGroup vg = (ViewGroup) v; for (int i = 0; i < vg.getChildCount(); i++) { String tag = getStringTagForView(vg.getChildAt(i)); if (tag != null && tag.contains(STICKY_TAG)) { stickyViews.add(vg.getChildAt(i)); } else if (vg.getChildAt(i) instanceof ViewGroup) { findStickyViews(vg.getChildAt(i)); } } } else { String tag = (String) v.getTag(); if (tag != null && tag.contains(STICKY_TAG)) { stickyViews.add(v); } } } private String getStringTagForView(View v) { Object tagObject = v.getTag(); return String.valueOf(tagObject); } private void hideView(View v) { if (Build.VERSION.SDK_INT >= 11) { v.setAlpha(0); } else { AlphaAnimation anim = new AlphaAnimation(1, 0); anim.setDuration(0); anim.setFillAfter(true); v.startAnimation(anim); } } private void showView(View v) { if (Build.VERSION.SDK_INT >= 11) { v.setAlpha(1); } else { AlphaAnimation anim = new AlphaAnimation(0, 1); anim.setDuration(0); anim.setFillAfter(true); v.startAnimation(anim); } } }
同时需要在res/values/attr.xml加入定义的属性:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="StickyScrollView"> <attr name="stuckShadowHeight" format="dimension" /> <attr name="stuckShadowDrawable" format="reference" /> </declare-styleable> </resources>
使用起来很简单,在xml布局中把某一个子View增加一个属性:
android:tag="sticky"
即可实现该子View在NestedScrollView中,当滚动到顶部后悬停挂靠在顶部不动,直到下一个粘性子View滚动上来把它顶飞,或者用户下拉,拉出上面的View。如xml代码:
<?xml version="1.0" encoding="utf-8"?> <zhangphil.test.StickyScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/holo_red_light" android:tag="sticky" android:text="姓名" android:textColor="@android:color/white" /> <TextView android:layout_width="match_parent" android:layout_height="280dp" android:background="@android:color/holo_blue_bright" android:gravity="center" android:text="zhang phil" android:textColor="@android:color/white" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/holo_red_light" android:tag="sticky" android:text="blog" android:textColor="@android:color/white" /> <TextView android:layout_width="match_parent" android:layout_height="280dp" android:background="@android:color/holo_orange_light" android:gravity="center" android:text="zhang phil csdn blog" android:textColor="@android:color/white" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/holo_red_light" android:tag="sticky" android:text="链接" android:textColor="@android:color/white" /> <TextView android:layout_width="match_parent" android:layout_height="280dp" android:background="@android:color/holo_purple" android:gravity="center" android:text="http://blog.csdn.net/zhangphil" android:textColor="@android:color/white" /> </LinearLayout> </zhangphil.test.StickyScrollView>
ViewPager与NestedScrollView套嵌会引起冲突,滑动不了的问题
https://blog.csdn.net/wjr1949/article/details/72479583?utm_source=itdadao&utm_medium=referral
发表评论
-
自定义Behavior实现AppBarLayout越界弹性效果
2017-03-31 09:33 10236一、继承AppBarLayout.Beha ... -
Android - 一种相似图片搜索算法的实现
2017-03-31 09:33 2570算法 缩小尺寸。 将图片缩小到8x8的尺寸,总共64个 ... -
使用SpringAnimation实现带下拉弹簧动画的 ScrollView
2017-03-30 11:30 2796在刚推出的 Support Library 25.3.0 里面 ... -
Android为应用添加角标(Badge)
2017-03-30 11:21 61041.需求简介 角标是什么意思呢? 看下图即可明了: 可 ... -
Android端与笔记本利用局域网进行FTP通信
2017-03-23 10:17 928先看图 打开前: 打开后: Activity类 ... -
PorterDuffColorFilter 在项目中的基本使用
2017-03-03 10:58 1301有时候标题栏会浮在内容之上,而内容会有颜色的变化,这时候就要求 ... -
ColorAnimationView 实现了滑动Viewpager 时背景色动态变化的过渡效果
2017-02-24 09:41 2172用法在注释中: import android.anima ... -
迷你轻量级全方向完美滑动处理侧滑控件SlideLayout
2017-01-16 16:53 2553纯手工超级迷你轻量级全方向完美滑动处理侧滑控件(比官方 sup ... -
Effect
2017-01-05 09:57 0https://github.com/JetradarMobi ... -
动态主题库Colorful,容易地改变App的配色方案
2016-12-27 14:49 2523Colorful是一个动态主题库,允许您很容易地改变App的配 ... -
对视图的对角线切割DiagonalView
2016-12-27 14:23 1075提供对视图的对角线切割,具有很好的用户定制 基本用法 ... -
仿淘宝京东拖拽商品详情页上下滚动黏滞效果
2016-12-26 16:53 3423比较常用的效果,有现成的,如此甚好!:) import ... -
让任意view具有滑动效果的SlideUp
2016-12-26 09:26 1663基本的类,只有一个: import android.a ... -
AdvancedWebView
2016-12-21 09:44 16https://github.com/delight-im/A ... -
可设置圆角背景边框的按钮, 通过调节色彩明度自动计算按下(pressed)状态颜色
2016-11-02 22:13 1864可设置圆角背景边框的的按钮, 通过调节色彩明度自动计算按下(p ... -
网络请求库相关
2016-10-09 09:35 62https://github.com/amitshekhari ... -
ASimpleCache一个简单的缓存框架
2015-10-26 22:53 2124ASimpleCache 是一个为android制定的 轻量级 ... -
使用ViewDragHelper实现的DragLayout开门效果
2015-10-23 10:55 3337先看一下图,有个直观的了解,向下拖动handle就“开门了”: ... -
保证图片长宽比的同时拉伸图片ImageView
2015-10-16 15:40 3680按比例放大图片,不拉伸失真 import android. ... -
向上拖动时,可以惯性滑动显示到下一页的控件DragLayout
2015-10-16 14:53 5529仿照淘宝和聚美优品,在商品详情页,向上拖动时,可以加载下一页。 ...
相关推荐
想做类似猫眼电影选场次会自动滚动到屏幕中间的效果 如图是最终效果 2.分析 实现这种效果的方法有三种: 1.直接使用原生CSS+js; 2.使用swiper,一屏显示多个item,点击item会自动滚动到中间 3.使用微信的scroll-view...
建立了开关磁阻电机定子系统磁固耦合振动微分方程;在考虑开关磁阻电机位移场与电磁场相互作用、相互影响的条件下,利用麦克斯韦张量法和磁路法,推导出开关磁阻电机定子系统所受径向电磁力;结合梁函数组合法解得定子...
定子绕组后的电机在运行中出现各种报错问题,本文详细介绍了电动机的运转原理和方法,对电动机出现的短路故障进行处理,对于电动机的正常工作有十分重要的作用,对异步电动 机定子绕组匝间短路故障进行了数字仿真,并...
支持横向纵向循环滚动和滑动居中,支持任意锚点布局(没有锚点限制),3种居中效果(不回弹,回弹,双向回弹)Grid(布局)不依赖任何脚本可以单独使用,不锁定子物体随意排序。WrapCententy(循环+居中)
易语言复制组件到指定子夹源码,复制组件到指定子夹
工艺过程中工序多、流程慢、效率低、产品质量难以保证,而且由于叠压而成的矽钢片的八个焊缝不是同步焊接,在焊接过程中热变形不同,因此加工成的Z4电机定子质量良莠不齐,无法保证Z4电机各种稳定的态势特性。...
ABB定子调压调试步骤 调试说明doc,ABB定子调压调试步骤 调试说明
将定子电流励磁分量和转矩分量作为状态变量,通过矢量变换的基本控制方法,给出了M-T坐标系下的状态方程,实现了磁通和转矩的解耦控制,并且分析了电压空间矢量控制(SVPWM)的原理,
MATLAB在双作用叶片泵定子曲线中的应用,周玉芳,毛君,双作用叶片泵定子曲线对叶片泵的各项性能都有重要影响,高次曲线是一种各项性能都比较优越的曲线,但方程比较复杂,如何绘制曲线
高压大接地系统发生接地故障时,故障点的零序电压会通过升压变压器高低压绕组间耦合电容传递到发电机侧,从而形成发电机定子虚拟接地现象。通过计算2伊300MW电厂高压母线单相及两相接地故障的接地零序电压,采用近似...
研究表明:建立的机电耦合模型可以研究转子轴承系统在故障激励下定子电流的特性,通过激励频率的不同能够辨别转子轴承系统的故障。该模型的建立为改进转子系统动力学和故障诊断提供了新的理论依据。
行业资料-电子功用-定子冲片、定子铁芯、定子和电机
汽车助力液压马达定子曲线,其中定子曲线包括了8种算法。示波器控件类,参照NI Labview中的波形控件进行编写的,功能十分强大,非常好用(在网上只能找到功能简单的波形控件,不适用,故自己写了一个),希望对其它...
目前大多数能绑定子目录的主机管理系统都通过建立多个虚拟网站的方式来变相实现解析到子目录的方式,这样做的缺点是无法对系统资源进行整体共享,只能单独限制某个所谓的子目录的资源,同时在IIS里面建立过多的虚拟...
在矢量控制和直接转矩控制的基础上,取长补短,提出一种新型的感应电动机按定子 磁场定 向控制的方法,采用定子电阻压降补偿和 电流转矩分量的闭环控制,实现了定子磁链和 电 磁转矩的协调控制。实验结果表明,该...
目前大多数能绑定子目录的主机管理系统都通过建立多个虚拟网站的方式来变相实现解析到子目录的方式,这样做的缺点是无法对系统资源进行整体共享,只能单独限制某个所谓的子目录的资源,同时在IIS里面建立过多的虚拟...
易语言源码易语言复制组件到指定子夹源码.rar
双水内冷发电机定子绝缘水管是发电机定子的重要部件,其严密性及完好性是保证发电机长期正常运行的关键,其检修相当重要,一旦出现定子绝缘水管漏水,会造成停机停炉,甚至主机损坏,给兴能发电公司带来不可估量的经济损失...