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

类似这种效果的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(一)的更多相关文章

  1. 带吸附效果的ViewPager(二)

    上篇实现了一个简单的吸附效果,那么这篇我们来实现上篇中所示的360软件详情页(带viewpager)的效果!先来参观下本篇所实现的效果图: 了解了上一篇的实现过程,那么本篇的效果无非是修改一下布局,将 ...

  2. js简单 图片版时钟,带翻转效果

    js简单 图片版时钟,带翻转效果 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"& ...

  3. android标题栏上面弹出提示框(二) PopupWindow实现,带动画效果

    需求:上次用TextView写了一个从标题栏下面弹出的提示框.android标题栏下面弹出提示框(一) TextView实现,带动画效果,  总在找事情做的产品经理又提出了奇葩的需求.之前在通知栏显示 ...

  4. android标题栏下面弹出提示框(一) TextView实现,带动画效果

    产品经理用的是ios手机,于是android就走上了模仿的道路.做这个东西也走了一些弯路,写一篇博客放在这里,以后自己也可用参考,也方便别人学习. 弯路: 1.刚开始本来用PopupWindow去实现 ...

  5. jquery制作弹出层带遮罩效果,点击阴影部分层消失

    jquery制作弹出层带遮罩效果,点击阴影部分层消失. 整体还是比较简单的. HTML代码很简单 <a href="#" class="big-link" ...

  6. js+css实现带缓冲效果右键弹出菜单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. 纯CSS3带动画效果导航菜单

    随着互联网的发展,网页能表现的东西越来越多.由最开始单纯的文字和链接构成的网页,到后来的表格布局,再到div+css模式,现在发展到了html+css3.网页能表达的东西越来越多,css3兴起已经很多 ...

  8. 收藏一个带动画效果的ScrollViewer以及ScrollBar的模板

    这里介绍一个带动画效果的ScrollViewer和ScrollBar,总共分为两个资源字典,直接拿来引用即可: 1 ScrollBarStyle.xaml <ResourceDictionary ...

  9. Android利用温度传感器实现带动画效果的电子温度计

    概述 Android利用温度传感器实现带动画效果的电子温度计. 详细 代码下载:http://www.demodashi.com/demo/10631.html 一.准备工作 需要准备一部带有温度传感 ...

随机推荐

  1. 主席树(BZOJ2653)

    考虑二分答案,设为k,将大于等于k的元素设为1,小于的设为-1,如果某一段的和>=0,说明这段的中位数>=k. 对于每组询问,二分完后查询新序列的最大子段和即可. 但是不能开n棵线段树,观 ...

  2. EffectiveTensorflow:Tensorflow 教程和最佳实践

    Tensorflow和其他数字计算库(如numpy)之间最明显的区别在于Tensorflow中的操作是符号. 这是一个强大的概念,允许Tensorflow进行所有类型的事情(例如自动区分),这些命令式 ...

  3. 从 vCenter Server 使用的数据库中清除旧数据 (2075138)(转)

    Document Id 2075138 Symptoms 免责声明: 本文为 Purging old data from the database used by VMware vCenter Ser ...

  4. C++Sizeof与Strlen的区别与联系

    一.sizeof    sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组.指针.类型.对象.函数等.    它的功能是:获得保 ...

  5. Java Web -【分页功能】详解

    分页简介 分页功能在网页中是非常常见的一个功能,其作用也就是将数据分割成多个页面来进行显示. 使用场景: 当取到的数据量达到一定的时候,就需要使用分页来进行数据分割. 当我们不使用分页功能的时候,会面 ...

  6. 欢迎大家来到DevLegal的博客

    申明:以下博文欢迎转载,转载请注明出处和作者 若非作者原创,则会标记出处与原作者,其余则为原创. 本人在校大学僧一枚,软件工程专业,希望通过将自己的学习心得与体会写出来,勉励自己学习,同时与大家一起分 ...

  7. 深入理解SpringCloud之引导程序应用上下文

    tips:我希望通过这篇文章来给对于bootstrap还不理解的朋友带来帮助.当然这篇文章不仅仅是讲解知识,我更希望给广大朋友带来学习与理解官方文档的一种思路.阅读本文前,建议大家对SpringBoo ...

  8. 利用Python进行数据分析——重要的Python库介绍

    利用Python进行数据分析--重要的Python库介绍 一.NumPy 用于数组执行元素级计算及直接对数组执行数学运算 线性代数运算.傅里叶运算.随机数的生成 用于C/C++等代码的集成 二.pan ...

  9. swing JTable 更新数据

    rowData 是将要更新的表格内数据,coloumnName是将要更新的表头数据. table是原本的table对象,更新数据的时候要用 DefaultTableModel 类~ /*更新table ...

  10. Java 8新特性:新语法方法引用和Lambda表达式及全新的Stream API

    新语法 方法引用Method references Lambda语法 Lambda语法在AndroidStudio中报错 Stream API 我正参加2016CSDN博客之星的比赛 希望您能投下宝贵 ...