1、效果图如下:

这效果用户体验还是很酷炫,今天我们就来讲解如何实现这个效果。

2、分析

为了方便理解,作图分析

如图所示,整个页面分为四个部分:

1、悬浮内容,floatView

2、顶部内容,headView

3、中间内容,与悬浮内容相同,middleView

4、商品详情展示页面,detailView

因为页面内容高度会超出屏幕,所以用Scrollview实现滚动,悬浮viewscrollview同级,都在一个帧布局或者相对布局中。

当y方向的滚动距离小于中间的内容middleView到顶部的距离时,middleView理所当然的会随这页面向上滑动而消失,我们显示悬浮view,从而实现middleView一直卡在顶部的效果。

当y方向滚动距离大于中间的内容middleView容到顶部的距离时,悬浮view隐藏即可。

通过分析,我们发现只要知道scrollview的滚动距离和middleView到顶部的高度即可。至此将复杂的交互特效变成了俩个简单的api。

3、第一种方法实现

3.1 获取middleView的到父容器顶部的距离

tv_title.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
mTitleTopAndHeight = tv_title.getTop(); tv_title.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});

在activity的oncreate()中直接通过view的getTop()方法获取到view的高度会返回0,这是因为此时view还没有绘制到界面,所以我们采用上面的方法给view设置监听获取,由于可能发生多次绘制,所以最后记得移除监听事件。

以下代码同样可以获取:

tv_title.post(new Runnable()
{
@Override
public void run()
{
mTitleTopAndHeight = tv_title.getTop();
}
});

利用post方法将操作放到队列中,等系统布局完成后执行队列中的事件,同样可以获取到正确的viewtop值。

3.2 获取垂直方向滚动距离

Scrollview的父类View中有个内容变化的方法onScrollChanged(),虽然该方法是protect的外部不可调用,但是在内部,当scrollview滚动时就会执行该方法,所以我们自定义一个MyScrollViewonScrollChanged()通过回调将滚动的距离传递给外部。

自定义scrollview完整代码如下:

public class MyScrollView extends ScrollView
{
private OnScrollListener mOnScrollListener; /**
* 是否用户手指触摸滑动
*/
private boolean mIsTouch = false; public MyScrollView(Context context)
{
this(context, null);
} public MyScrollView(Context context, AttributeSet attrs)
{
this(context, attrs, );
} public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
} @Override
protected void onScrollChanged(int l, int t, int oldl, int oldt)
{
super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null)
{
mOnScrollListener.onScroll(t, mIsTouch ? OnScrollListener.SCROLL_STATE_TOUCH_SCROLL : OnScrollListener.SCROLL_STATE_FLING);
}
} @Override
public boolean onTouchEvent(MotionEvent ev)
{
switch (ev.getAction())
{
case MotionEvent.ACTION_MOVE:
mIsTouch = true; break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mIsTouch = false; break;
} return super.onTouchEvent(ev);
} public void setOnScrollListener(OnScrollListener onScrollListener)
{
mOnScrollListener = onScrollListener;
} public interface OnScrollListener
{
/**
* 用户手指拖动滚动
*/
int SCROLL_STATE_TOUCH_SCROLL = 0x0; /**
* 惯性滑行滚动
*/
int SCROLL_STATE_FLING = 0x1; /**
* 滚动时的回调
*
* @param scrollY Y方向滚动的距离
* @param scroll_state 当前滚动状态:自由滚动或者手势拖动滚动
*/
void onScroll(int scrollY, int scroll_state);
}
}

3.3 使用

acitivity中给scrollview设置自定义滚动监听事件即可

mScrollView.setOnScrollListener(new MyScrollView.OnScrollListener()
{
@Override
public void onScroll(int scrollY, int state)
{
Log.d("onScroll: ", scrollY + "" + "----------- state:" + state); if (scrollY <= mTitleTopAndHeight)
{
tv_float.setVisibility(View.INVISIBLE);
} else
{
tv_float.setVisibility(View.VISIBLE);
}
}
});

这样,通过垂直方法的滚动值来控制floatView的显示隐藏,

tv_float.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
mScrollView.onTouchEvent(event);
return false;
}
});

给悬浮view设置触摸监听,将用户手势传递给scrollView,这样用户滑动悬浮view时,内容区域也可以跟随滚动。

下面是布局代码

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
> <com.example.qike.scrolltitle.MyScrollView
android:id="@+id/sv_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"> <TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="商品图片"/> <TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#a3c"
android:gravity="center"
android:text="标题view"/> <TextView
android:layout_width="match_parent"
android:layout_height="600dp"
android:background="#a2bb"
android:gravity="center"
android:text="详情页面"/>
</LinearLayout>
</com.example.qike.scrolltitle.MyScrollView> <TextView
android:id="@+id/tv_float"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#a3c"
android:gravity="center"
android:text="标题view"
android:visibility="invisible"/> </RelativeLayout>

4、第二种方式

本方法与第一种方式的区别就是获取滚动位置的方法不同,该方法更简单一些:

mScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener()
{
@Override
public void onScrollChanged()
{
int scrollY = mScrollView.getScrollY();
if (scrollY <= mTitleTopAndHeight)
{
tv_float.setVisibility(View.INVISIBLE);
} else
{
tv_float.setVisibility(View.VISIBLE);
}
}
});

可能有读者要问,既然有这种简单的方法直接设置监听,为什么还介绍第一种方法。细心的你可能已经发现,在第一种方法中,我在自定义的监听事件中,还回调了代表当前回调状态的参数statue,因为很多app,在用户手动拖动滚动跟惯性滚动的处理是不能的。比如淘宝商品详情页面,当达到边界值中间viewtop值时,只有用户手动拖动一段距离后才会拉出底部的详情类容,而惯性滑动的话只会停在那里。

5、总结

以上就是关于安卓实现按钮随着上下滚动而悬浮顶在固定位置的方法,希望本文的内容对大家开发Android能有所帮助。

Android 仿电商app商品详情页按钮浮动效果的更多相关文章

  1. Android跳转淘宝、京东APP商品详情页

    import Android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; imp ...

  2. 自己定义ViewGroup实现仿淘宝的商品详情页

    近期公司在新版本号上有一个须要. 要在首页加入一个滑动效果, 详细就是仿照X宝的商品详情页, 拉到页面底部时有一个粘滞效果, 例如以下图 X东的商品详情页,假设用户继续向上拉的话就进入商品图文描写叙述 ...

  3. 微信小程序电商实战-商品详情(上)

    先看一下今天要实现的小程序商品详情页吧!   商品详情.gif 本期我们要实现小程序商品详情页的头部标题.头部轮播.商品详情浮动按钮和商品内页布局. 一.设置头部标题 如上图所示,头部标题是商品详情 ...

  4. android仿今日头条App、多种漂亮加载效果、选择器汇总、记事本App、Kotlin开发等源码

    Android精选源码 android漂亮的加载效果 android各种 选择器 汇总源码 Android仿bilibili搜索框效果 Android记事本app.分类,涂鸦.添加图片或者其他附件 仿 ...

  5. 仿京东淘宝商品详情页属性选择js效果

    在网上找了好久发现都不符合要求就自己摸索写了一个,用到了linq.js这个linq to js 扩展,不然用纯JS遍历json查询要死人啊 demo:http://123.207.28.46:8086 ...

  6. Android仿淘宝继续上拉进入商品详情页的效果,使用双Fragment动画切换;

    仿淘宝继续上拉进入商品详情页的效果,双Fragment实现: 动画效果: slide_above_in.xml <?xml version="1.0" encoding=&q ...

  7. 电商 APP 下单页(俗称车2) 业务流程概要设计

    购物车是电商APP的一个关键功能点,一般购物车包含 3-4 个页面,分别是: 1.购物车的商品列表页 2.商品下单页 3.订单付款页面 4.订单付款成功页面 由于现有购物车逻辑相对混乱,这里重新整理一 ...

  8. Android点击跳转到淘宝的某一商品详情页或者某一店铺页面

    最近项目的有个需求是点击购买资料按钮进入淘宝界面,简单分析一下,如果用户手机有淘宝就打开淘宝的页面,没有的话也可以选择使用webView进行展示,还是使用手机浏览器进行展示. 判断有无淘宝的代码就不贴 ...

  9. Android通用框架设计与完整电商APP开发系列文章

    作者|傅猿猿 责编|Javen205 有福利 有福利 有福利 鸣谢 感谢@傅猿猿 邀请写此系列文章 Android通用框架设计与完整电商APP开发 课程介绍 [导学视频] [课程详细介绍] 以下是部分 ...

随机推荐

  1. 做c语言的码农专业发展方向

    写了几年C语言代码,最近在思索,何去何从比较好? 搜索了一下,发现几个答案: 2015年10月编程语言排行榜 丢开C语言在教学应用外.在目前C语言的实际应用中.常见的应用的情景有如下: 内核/驱动,b ...

  2. Python最小二乘法解非线性超定方程组

    求解非线性超定方程组,网上搜到的大多是线性方程组的最小二乘解法,对于非线性方程组无济于事. 这里分享一种方法:SciPy库的scipy.optimize.leastsq函数. import numpy ...

  3. Storm在zookeeper上的目录结构

    storm操作zookeeper的主要函数都定义在命名空间backtype.storm.cluster中(即cluster.clj文件中). backtype.storm.cluster定义了两个重要 ...

  4. JavaScript中的真和假,==和===, 不等

    咋JS中,下面这些值表示 “假”: "" (empty string) 0,-0,NaN (invalid number) null, undefined false 除了上面这些 ...

  5. JavaScript 异常 Exceptions

    JavaScript提供了一套异常处理机制. 异常是干扰程序的正常流程的不寻常(但并非完全是出乎意料的)的事故. 当发现这样的事故时,你的程序应该抛出一个异常. throw语句中断函数的执行. 它应该 ...

  6. 【关于msyql5.6创建存储过程的一些记录】

    -- 秒杀执行存储过程DELETE $$ -- console的结束符号由;转换成 $$-- in输入参数:out:输出参数-- ROW_COUNT():返回上条dml影响的条数: 小于0:sql语句 ...

  7. Unix Tutorial Eight

    1.UNIX 变量 变量是在运行时将信息从shell传递到程序的一种方式.程序在特定的变量中查找“在环境中”,如果发现它们将使用存储的值.有些是由系统设置的,另一些是由你设置的,还有一些是由shell ...

  8. CTO成长之路分享会

    1. 李宏玮,纪源资本合伙人GGV,设计无人机,典型的投资: VC做投资,收入利润上市技术团队,架构支撑前沿科技,以后牛逼公司以技术为主 2. 小红书tiger2003加入谷歌,之前学phpgoogl ...

  9. 20个问题(状压dp)

    20个问题(状压dp) 有n(<=128)个物体,m(<=11)个特征.每个物体用一个m位01串表示,表示每个特征是具备还是不具备.我在心里想一个物体,由你来猜.你每次可以询问一个特征,然 ...

  10. 洛谷P1054 等价表达式

    P1054 等价表达式 题目描述 明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的 ...