- 浏览: 5820851 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (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 10369一、继承AppBarLayout.Beha ... -
Android - 一种相似图片搜索算法的实现
2017-03-31 09:33 2623算法 缩小尺寸。 将图片缩小到8x8的尺寸,总共64个 ... -
使用SpringAnimation实现带下拉弹簧动画的 ScrollView
2017-03-30 11:30 2850在刚推出的 Support Library 25.3.0 里面 ... -
Android为应用添加角标(Badge)
2017-03-30 11:21 61771.需求简介 角标是什么意思呢? 看下图即可明了: 可 ... -
Android端与笔记本利用局域网进行FTP通信
2017-03-23 10:17 980先看图 打开前: 打开后: Activity类 ... -
PorterDuffColorFilter 在项目中的基本使用
2017-03-03 10:58 1355有时候标题栏会浮在内容之上,而内容会有颜色的变化,这时候就要求 ... -
ColorAnimationView 实现了滑动Viewpager 时背景色动态变化的过渡效果
2017-02-24 09:41 2222用法在注释中: import android.anima ... -
迷你轻量级全方向完美滑动处理侧滑控件SlideLayout
2017-01-16 16:53 2596纯手工超级迷你轻量级全方向完美滑动处理侧滑控件(比官方 sup ... -
Effect
2017-01-05 09:57 0https://github.com/JetradarMobi ... -
动态主题库Colorful,容易地改变App的配色方案
2016-12-27 14:49 2565Colorful是一个动态主题库,允许您很容易地改变App的配 ... -
对视图的对角线切割DiagonalView
2016-12-27 14:23 1118提供对视图的对角线切割,具有很好的用户定制 基本用法 ... -
仿淘宝京东拖拽商品详情页上下滚动黏滞效果
2016-12-26 16:53 3494比较常用的效果,有现成的,如此甚好!:) import ... -
让任意view具有滑动效果的SlideUp
2016-12-26 09:26 1707基本的类,只有一个: import android.a ... -
AdvancedWebView
2016-12-21 09:44 16https://github.com/delight-im/A ... -
可设置圆角背景边框的按钮, 通过调节色彩明度自动计算按下(pressed)状态颜色
2016-11-02 22:13 1921可设置圆角背景边框的的按钮, 通过调节色彩明度自动计算按下(p ... -
网络请求库相关
2016-10-09 09:35 62https://github.com/amitshekhari ... -
ASimpleCache一个简单的缓存框架
2015-10-26 22:53 2178ASimpleCache 是一个为android制定的 轻量级 ... -
使用ViewDragHelper实现的DragLayout开门效果
2015-10-23 10:55 3415先看一下图,有个直观的了解,向下拖动handle就“开门了”: ... -
保证图片长宽比的同时拉伸图片ImageView
2015-10-16 15:40 3733按比例放大图片,不拉伸失真 import android. ... -
向上拖动时,可以惯性滑动显示到下一页的控件DragLayout
2015-10-16 14:53 5582仿照淘宝和聚美优品,在商品详情页,向上拖动时,可以加载下一页。 ...
相关推荐
想做类似猫眼电影选场次会自动滚动到屏幕中间的效果 如图是最终效果 2.分析 实现这种效果的方法有三种: 1.直接使用原生CSS+js; 2.使用swiper,一屏显示多个item,点击item会自动滚动到中间 3.使用微信的scroll-view...
首先,在电机静止状态下,通过在定子端施加电压脉冲,可以估算出泄漏电感和定子转子的直流电阻。接着,将功率转换器切换到电流控制模式,测量得到的定子电压数据用于估算定子电阻和互感。最后,在电机运行于不同速度...
定子电流励磁分量是电机控制系统中的一个重要概念,尤其在交流电动机的矢量控制技术中占有核心地位。在现代工业自动化领域,精确控制电机的运行性能是至关重要的,而定子电流励磁分量的掌握对于实现这一目标至关重要...
在易语言中,“复制组件到指定子夹”是一个常见的操作,尤其在软件开发过程中,我们常常需要将组件文件复制到程序的特定目录,以便于程序的运行和更新。 首先,我们需要了解易语言中的“组件”。组件是具有特定功能...
在介绍这种工装设备的设计思路、结构性能及工作过程之前,我们有必要对小型电机、单端电机及定子铁芯等概念进行梳理。 小型电机是指体积较小、功率较低的一类电机。它们广泛应用于家用电器、办公自动化设备、玩具...
MATLAB在叶片泵定子曲线设计中的应用 叶片泵作为一种常见的液压元件,广泛应用于工业生产及各种机械设备中。定子内表面的过渡曲线对于叶片泵的性能有着直接的影响,其中排量、输出流量脉动、冲击振动、噪声、效率和...
支持横向纵向循环滚动和滑动居中,支持任意锚点布局(没有锚点限制),3种居中效果(不回弹,回弹,双向回弹)Grid(布局)不依赖任何脚本可以单独使用,不锁定子物体随意排序。WrapCententy(循环+居中)
然而,电机在实际运行过程中,定子电流的幅值波动是一个需要重点关注的问题,因为它将直接影响到电机及驱动系统的稳定性和可靠性。 首先,我们要了解定子电流波动对电机性能的影响。电流波动会引起驱动电路产生负序...
总结所述,"电子功用-定子冲片、定子铁芯、定子和电机"这份资料深入剖析了电机的核心组件,从冲片设计到铁芯构造,再到定子绕组的功能,全面揭示了电机如何将电能转化为机械能的过程。这份文档对于从事电机设计、...
定子叠加机是一种专用于Z4电机定子制造的机械设备,旨在解决当前手动工艺存在的问题,如工序繁多、流程缓慢、效率低下和产品质量不稳定。传统的Z4电机定子制造工艺依赖于手工叠压和焊接,导致焊缝热变形不一致,影响...
然而,矢量控制高度依赖于准确的转子参数,尤其是转子电阻,这使得其在实际应用中的鲁棒性受到限制。 - **直接转矩控制**:这种控制方法通过直接控制电机的转矩和磁链,简化了控制系统结构,提高了系统的响应速度...
标题中的“行业资料-电子功用-内转子式和外定子式的直流电动力机和单、双轮滚动式电刷的说明分析”表明,这是一个关于电子工程领域,特别是电机技术的专业资料。它涵盖了两种不同结构的直流电动机——内转子式和外...
综合来看,定子中国虚拟主机系统提供了一套完整的网站管理解决方案,涵盖从基础的域名绑定到高级的数据库管理。对于个人用户和小型企业来说,它降低了搭建和维护网站的技术门槛;对于开发者,它提供了源码学习和二次...
异步电机的转速与转矩之间的关系受到定子电流的影响。在额定条件下,电机的转速由同步转速减去滑差决定,滑差又与电机的电磁转矩有关。当定子电流增大时,电机产生的电磁转矩也增大,从而提高电机的加速能力;反之,...
在描述中提到了“位图旋转”和“XFORM PlgBlt”,这暗示了源码可能涉及到图形界面或可视化模拟,用于展示电机定子槽的几何形状或者进行电机结构的动态演示。 位图旋转是一项常见的图像处理技术,它在计算机图形学中...