带吸附效果的ViewPager(一)
什么叫吸附效果?先看一个示例更为直观,借用网上的一个效果图:

类似这种效果的app很多,网上的实现方法也是很多,但各种重写各种监听又令人不胜其烦,今日突发奇想,顺着自己的思路实现了类似的效果,不敢独享,特来分享给大家!
做事要一步一步来,不能一口吃胖,知道原理,接下来的事情就好办了!所以第一篇,暂且实现一个简单的效果,如图:
实现思路(原理):
1.ScrollView
外层ScrollView不必说了!
2.滑动监听
我们要实现这种效果,那么ScrollView的滑动监听必不可少,当scrollview上滑动至图中的snapbar顶部位置时以及下滑出snapbar顶部位置时对该吸附控件的操作!网上大多数是通过重写View来实现的,本人则取巧通过事先在顶部位置布局的控件以显示隐藏来实现的,当scrollview上滑动至snapbar顶部位置显示控件,下滑至该位置时再隐藏,是不是很简单?但需注意一点是,我们需要计算snapbar以上部分布局的高度,才能在scrollview滑动监听中判断是否滑动到了这一位置:
本人将这部分的高度固定为160dp,只需将160dp转换为px就可以了,另外我们在类似这样的布局时也尽量能固定顶部这一部分的高度,方便计算,如果使用的是wrap_parent怎需动态计算高度,相对麻烦!
3.吸附控件布局
布局时,是需要两个相同的snapbar布局的,一个是跟随scrollview滑动的,一个是固定在顶部且初始状态为隐藏的。如何操作即第二步的操作方法!
因为6.0以前的SDK,ScrolView是无法直接使用onScrollChanged来监听滑动距离的,因此我们需要稍稍重写下ScrollView并自定义一个接口来将onScrollChanged事件暴露出来:
package com.byl.snappingviewpager;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;
/**
* Created by baiyuliang on 2016-5-5.
*/
public class MyScrollView extends ScrollView {
private ScrollViewListener scrollViewListener = null;
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScrollViewListener(ScrollViewListener scrollViewListener) {
this.scrollViewListener = scrollViewListener;
}
@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if (scrollViewListener != null) {
scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
}
}
public interface ScrollViewListener {
void onScrollChanged(MyScrollView scrollView, int x, int y, int oldx, int oldy);
}
}
snapbar上部高度计算:
snapbar_y = dip2px(this, 160);//注意你的snapbar以上部分的高度值,将其转换为px(最好设置为固定值,如果非固定,则要动态计算高度)
/**
* 将dp转px
*
* @param context
* @param dpValue
* @return
*/
public int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
滑动监听:
scrollView.setScrollViewListener(new MyScrollView.ScrollViewListener() {
@Override
public void onScrollChanged(MyScrollView scrollView, int x, int y, int oldx, int oldy) {
if (y >= snapbar_y) {
rg_snapbar_top.setVisibility(View.VISIBLE);
} else {
rg_snapbar_top.setVisibility(View.GONE);
}
}
});
就此简单几步就可以实现了,哈哈!
MainActivity:
package com.byl.snappingviewpager;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
MyScrollView scrollView;
TextView tv_snapbar_top,tv_snapbar;
int snapbar_y;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
snapbar_y=dip2px(this,160);//注意你的snapbar以上部分的高度值,将其转换为px(最好设置为固定值,如果非固定,则要动态计算高度)
}
private void initView() {
scrollView= (MyScrollView) findViewById(R.id.scrollView);
tv_snapbar_top= (TextView) findViewById(R.id.tv_snapbar_top);
tv_snapbar= (TextView) findViewById(R.id.tv_snapbar);
scrollView.setScrollViewListener(new MyScrollView.ScrollViewListener() {
@Override
public void onScrollChanged(MyScrollView scrollView, int x, int y, int oldx, int oldy) {
if(y>=snapbar_y){
tv_snapbar_top.setVisibility(View.VISIBLE);
}else{
tv_snapbar_top.setVisibility(View.GONE);
}
}
});
tv_snapbar_top.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "snapbar_top", Toast.LENGTH_SHORT).show();
}
});
tv_snapbar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "snapbar", Toast.LENGTH_SHORT).show();
}
});
}
/**
* 将dp转px
* @param context
* @param dpValue
* @return
*/
public int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
activity_main.xml(为了方便起见,列表数据是直接放在了布局文件中的):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#EEEEEE"
tools:context="com.byl.snappingviewpager.MainActivity">
<com.byl.snappingviewpager.MyScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="@color/colorPrimaryDark">
<ImageView
android:id="@+id/iv_headView"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:src="@mipmap/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/iv_headView"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:text="白玉梁"
android:textColor="#FFFFFF" />
</RelativeLayout>
<TextView
android:id="@+id/tv_snapbar"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#FF6600"
android:gravity="center_vertical"
android:paddingLeft="5dp"
android:textColor="#FFFFFF"
android:text="snapbar" />
<!-- 以下为列表内容,为了方便,直接写在了布局中 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
android:textColor="#666666" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题1"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
android:textColor="#666666" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题2"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
android:textColor="#666666" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题3"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
android:textColor="#666666" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题4"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
android:textColor="#666666" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题5"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
android:textColor="#666666" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题6"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
android:textColor="#666666" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题7"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
android:textColor="#666666" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题8"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
android:textColor="#666666" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题9"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
android:textColor="#666666" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题10"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容"
android:textColor="#666666" />
</LinearLayout>
</LinearLayout>
</com.byl.snappingviewpager.MyScrollView>
<TextView
android:id="@+id/tv_snapbar_top"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#FF6600"
android:textColor="#FFFFFF"
android:gravity="center_vertical"
android:paddingLeft="5dp"
android:text="snapbar"
android:visibility="gone" />
</RelativeLayout>
带吸附效果的ViewPager(一)的更多相关文章
- 带吸附效果的ViewPager(二)
上篇实现了一个简单的吸附效果,那么这篇我们来实现上篇中所示的360软件详情页(带viewpager)的效果!先来参观下本篇所实现的效果图: 了解了上一篇的实现过程,那么本篇的效果无非是修改一下布局,将 ...
- js简单 图片版时钟,带翻转效果
js简单 图片版时钟,带翻转效果 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"& ...
- android标题栏上面弹出提示框(二) PopupWindow实现,带动画效果
需求:上次用TextView写了一个从标题栏下面弹出的提示框.android标题栏下面弹出提示框(一) TextView实现,带动画效果, 总在找事情做的产品经理又提出了奇葩的需求.之前在通知栏显示 ...
- android标题栏下面弹出提示框(一) TextView实现,带动画效果
产品经理用的是ios手机,于是android就走上了模仿的道路.做这个东西也走了一些弯路,写一篇博客放在这里,以后自己也可用参考,也方便别人学习. 弯路: 1.刚开始本来用PopupWindow去实现 ...
- jquery制作弹出层带遮罩效果,点击阴影部分层消失
jquery制作弹出层带遮罩效果,点击阴影部分层消失. 整体还是比较简单的. HTML代码很简单 <a href="#" class="big-link" ...
- js+css实现带缓冲效果右键弹出菜单
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 纯CSS3带动画效果导航菜单
随着互联网的发展,网页能表现的东西越来越多.由最开始单纯的文字和链接构成的网页,到后来的表格布局,再到div+css模式,现在发展到了html+css3.网页能表达的东西越来越多,css3兴起已经很多 ...
- 收藏一个带动画效果的ScrollViewer以及ScrollBar的模板
这里介绍一个带动画效果的ScrollViewer和ScrollBar,总共分为两个资源字典,直接拿来引用即可: 1 ScrollBarStyle.xaml <ResourceDictionary ...
- Android利用温度传感器实现带动画效果的电子温度计
概述 Android利用温度传感器实现带动画效果的电子温度计. 详细 代码下载:http://www.demodashi.com/demo/10631.html 一.准备工作 需要准备一部带有温度传感 ...
随机推荐
- [hdu5608]function
题意:$\sum_{d|n}f(d)=n^{2}-3n+2$,求$\sum_{i=1}^{n}f(i)\mod 10^{9}+7$ , $n \leqslant 10^{9}$ $\left( T \ ...
- linux办公软件的使用和病毒防范
今天看了linux办公软件的使用和病毒防范,特做此记录,将不熟悉的内容总结一下: openoffice 和liberoffice是可以跨平台的两款办公软件.odt是openoffice的扩展名.lib ...
- ubuntu 16.04 安装 tensorflow-gpu 包括 CUDA ,CUDNN,CONDA
ubuntu 16.04 安装 tensorflow-gpu 包括 CUDA ,CUDNN,CONDA 显卡驱动装好了,如图: 英文原文链接: https://github.com/williamFa ...
- python2.7入门---运算符
已经分享过变量类型的基本概念了,接下来就研究了一下运算符的基础知识.接下来我们就来看一下内容.举个简单的例子 4 +5 = 9 .例子中,4 和 5 被称为操作数,"+" ...
- OVF文件考究
一.什么是OVF文件 开源虚拟化格式OVF(不同于小写的ovf)文件是一种开源的文件规范,它描述了一个开源.安全.有效.可拓展的便携式虚拟打包以及软件分布格式,它一般有几个部分组成,分别是o ...
- 构建纯TypeScript应用
构建纯TypeScript应用 现在只有命令行应用的例子. 前言 现在,应用开发的趋势是命令行接口应用和Web应用. node.js 和 typescript的崛起所以,这里讨论如何创建纯的TypeS ...
- vscode 搭建go开发环境的13个插件的安装
由于网的问题 大家都不能直接go get 这里从易到难按难度给大家推荐几种方法 最简单的FQ 但是能FQ你还不能装 请问是假的FQ吗? 第一 用git 直接git反而能从那边趴下代码 但是要自己go ...
- SQL语句常见DDL/DML/DCL操作部分试题(一)
创建三个空表emp1,emp2,emp3,结构参考emp表 CREATE TABLE EMP1 AS SELECT * FROM EMP WHERE 1=2; CREATE TABLE EMP2 AS ...
- VS2010 win7 64位安装后新建项目生成时错误:LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
解决方案:VS2010在经历一些更新后,建立Win32 Console Project时会出“error LNK1123” 错误,解决方案为将 项目|项目属性|配置属性|清单工具|输入和输出|嵌入清单 ...
- LintCode题解之斐波纳契数列
直接使用递归的方法会导致TLE,加个缓存就好了: public class Solution { private Integer[] buff = new Integer[1000]; /* * @p ...