ScrollView增加标题并且控制显示和隐藏

转载请著名出处:
http://blog.csdn.net/forwardyzk/article/details/46636997

我们知道XLIstview有上拉刷新和下拉加载,现在模拟一下XlistView的下拉刷新,使Scroller也有标题,通过滑动控制标题的显示和隐藏.

我们先来看一下效果:

首先创建标题View

scroller_header.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/darker_gray">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:gravity="center_vertical"
        android:text="我是第一个孩子"
        android:textSize="25sp" />
</LinearLayout>

自定义标题控件

public class ScrollHeader extends LinearLayout {
    private LinearLayout mContainer;
    private Context mContext;

    public ScrollHeader(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        initView();
    }

    private void initView() {
        // 初始情况
        LayoutParams lp = new LayoutParams(
                android.view.ViewGroup.LayoutParams.FILL_PARENT, 0);
        mContainer = (LinearLayout) LayoutInflater.from(mContext).inflate(
                R.layout.scroller_header, null);

        addView(mContainer, lp);
        setGravity(Gravity.BOTTOM);
    }

    /**
     * 设置显示的高度
     *
     * @param height
     */
    public void setVisiableHeight(int height) {
        if (height < 0)
            height = 0;
        LayoutParams lp = (LayoutParams) mContainer
                .getLayoutParams();
        lp.height = height;
        mContainer.setLayoutParams(lp);
    }

    /**
     * 获取显示的高度
     *
     * @return
     */
    public int getVisiableHeight() {
        return mContainer.getHeight();
    }
}

开始默认设置mContainer的高度为0,就是默认的不显示,

setVisiableHeight动态设置标题的高度

getVisiableHeight获取标题的高度

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.example.yang.listviewtitle.view.MyScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <com.example.yang.listviewtitle.view.ScrollHeader
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:layout_marginBottom="10dp"
                android:background="@android:color/holo_blue_dark"
                android:gravity="center_vertical"
                android:padding="10dp"
                android:text="我是第2个孩子" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:layout_marginBottom="10dp"
                android:background="@android:color/holo_blue_dark"
                android:gravity="center_vertical"
                android:padding="10dp"
                android:text="我是第3个孩子" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:layout_marginBottom="10dp"
                android:background="@android:color/holo_blue_dark"
                android:gravity="center_vertical"
                android:padding="10dp"
                android:text="我是第4个孩子" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:layout_marginBottom="10dp"
                android:background="@android:color/holo_blue_dark"
                android:gravity="center_vertical"
                android:padding="10dp"
                android:text="我是第5个孩子" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:layout_marginBottom="10dp"
                android:background="@android:color/holo_blue_dark"
                android:gravity="center_vertical"
                android:padding="10dp"
                android:text="我是第6个孩子" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:layout_marginBottom="10dp"
                android:background="@android:color/holo_blue_dark"
                android:gravity="center_vertical"
                android:padding="10dp"
                android:text="我是第7个孩子" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:layout_marginBottom="10dp"
                android:background="@android:color/holo_blue_dark"
                android:gravity="center_vertical"
                android:padding="10dp"
                android:text="我是第8个孩子" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:layout_marginBottom="10dp"
                android:background="@android:color/holo_blue_dark"
                android:gravity="center_vertical"
                android:padding="10dp"
                android:text="我是第9个孩子" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:layout_marginBottom="10dp"
                android:background="@android:color/holo_blue_dark"
                android:gravity="center_vertical"
                android:padding="10dp"
                android:text="我是第10个孩子" />

        </LinearLayout>

    </com.example.yang.listviewtitle.view.MyScrollView>

</LinearLayout>

这里面使用了自定义的ScrollerView和在自定义的ScrollerView中使用了自定义的标题,这里要注意的是:

1.MyScrllerView的子View是Linearlayout,如果要换成其他的布局,要在代码中做相应的改变

2.要把自定义的标题作为MyScrllerView子View的第一个子View.

自定义MyScrollerView

public class MyScrollView extends ScrollView {
    private ScrollHeader mHeader;
    private float mLastY = -1;
    private Context mContext;
    private int MAX_VISI_HEIGHT;
    private Scroller mScroller;

    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        MAX_VISI_HEIGHT = getScreenHeight() / 3;
        mScroller = new Scroller(context, new DecelerateInterpolator());

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取Scroller的第一个孩子,就是包裹所有孩子的View
        LinearLayout firstLL = (LinearLayout) getChildAt(0);
        mHeader = (ScrollHeader) firstLL.getChildAt(0);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (mLastY == -1) {
            mLastY = ev.getRawY();
        }
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastY = ev.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                final float deltaY = ev.getRawY() - mLastY;
                mLastY = ev.getRawY();
                if (deltaY > 0) {
                    int height = mHeader.getVisiableHeight();
                    if (MAX_VISI_HEIGHT > height) {
                        //更新header高度
                        mHeader.setVisiableHeight((int) deltaY + height);
                    }

                }

                break;
            case MotionEvent.ACTION_UP:
                Log.d("MyScrollerView", "MOVE_UP");
                if (mHeader.getVisiableHeight() > 0) {
                    resetHeaderHeight();
                }

                break;
        }
        return super.onTouchEvent(ev);
    }

    /**
     * 获取屏幕的高度
     *
     * @return
     */
    private int getScreenHeight() {
        WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);
        return displayMetrics.heightPixels;
    }

    private void resetHeaderHeight() {
        int height = mHeader.getVisiableHeight();
        Log.d("MyScrollerView", "移动的高度:" + (0 - height));
        mScroller.startScroll(0, height, 0, 0 - height,
                400);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            mHeader.setVisiableHeight(mScroller.getCurrY());
            postInvalidate();
        }
        super.computeScroll();
    }
}

设计思路:

1.获取到不局文件中的标题View

2.通过监听滑动ScrllerView手势,如果是向下拉,那么计算出滑动的距离,

3.讲滑动的距离来移动标题View

4.当手离开了屏幕,那么使用Scroller来平移标题View到初始的位置

在onMeasure中获取要操作的标题View

//获取Scroller的第一个孩子,就是包裹所有孩子的View
        LinearLayout firstLL = (LinearLayout) getChildAt(0);
        mHeader = (ScrollHeader) firstLL.getChildAt(0);

在onTouchEvent的MotionEvent.MOVE_MOVE中计算出滑动的具体,动态设置标题View的高度

在onTouchEvent的MotionEvent.MOVE_UP:设置标题的回到初始的位置

 mScroller.startScroll(0, height, 0, 0 - height,
                400);
        invalidate();

在computeScroll()方法中动态的设置标题View的高度,否则就不会有平移的效果.

@Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            mHeader.setVisiableHeight(mScroller.getCurrY());
            postInvalidate();
        }
        super.computeScroll();
    }

滑动距离的判断:不能操作屏幕的三分之一的高度,这个高度可以根据需求来改变

回弹的时间:现在设置的400毫秒,这个时间可以根据需求来改变.

最主要的标题的显示:需更改变,只需更改scroller_header.xml布局.

到此效果已经实现.

源码下载:http://download.csdn.net/detail/forwardyzk/8838455

时间: 2024-10-04 02:14:41

ScrollView增加标题并且控制显示和隐藏的相关文章

JavaScript控制显示与隐藏

<!DOCTYPE> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>js显示隐藏层</title> <script> function look(targetid,objN){ var target=document.getElementById(

cesium添加多个geojson文件并分别控制显示和隐藏

/*获取geojson数据*/ function get_geojson(name,h,n){ let x=document.getElementById(n); if(x.className === "la"){ loadgeojson(name,h,n); x.className = "la2"; }else{ x.className = "la"; let len = viewer.dataSources.length; if(len>

Dynamics CRM 2013 停用和激活按钮的显示与隐藏

CRM中命令栏上的有些按钮是可以通过权限控制显示和隐藏的,比如新建.保存.保存并关闭.删除等,但惟独激活和停用无法控制,但我们还是可以用权限去控制,只是稍微绕了那么一下. 这里就要涉及到按钮的自定义了,说到按钮的自定义那肯定得用到ribbon workbench,这个工具如何使用不在本文阐述的范围内.见下图,右击active按钮选择customise command(我这边已经生成过了所以是灰的),点击display rule 具体的参数啥意思就不解释了,最后一个参数你是要create呢还是de

微信小程序之多列表的显示和隐藏功能(附源码)

今天在项目碰到一个问题,之前在项目首页实现单列表的显示和隐藏,通过wx:if判断就可实现,现在要实现多列表的单项显示和隐藏功能应该如何实现呢?如果还用wx:if实现的话会出现点击一个列表项,多个列表同时显示和隐藏,明显不适合功能需求,然后简单地查了资料也没发现有类似的功能,最后思考一番后,慢慢地理清了思路... 效果图: 实现思路: 实现单个列表的显示和隐藏应该使用唯一元素让程序知道你应该显示和隐藏哪个列表项,可以用数据的id: css中定义一个hidden{display:none}控制显示和

通过设置标签class值控制标签的显示与隐藏

需求背景如下: 原项目居民.单位.计量三模块共用一个jsp文件,显示的页面也顺理成章的统一了,幸亏没有调用同一个js,在此基础上要求居民和单位计量的分离,即居民的显示居民的相关信息,单位和计量的显示相同的信息,时间久远,仅有的未修改前的页面截图如下(红框内字段已替换成红字): 需求分析: (1)项目中添加字段并实现增删改查功能 (2)页面的展示,居民显示居民相关字段,单位和计量显示单位相关字段 字段添加这里不再赘述,主要分析页面的显示 刚开始拿到这个需求,打算另外新建单位相关的jsp页面(只包含

js控制tr显示和隐藏

很久没有写代码,最近新接了一个项目,开始记录自己开发过程中遇到的一些问题. 关于js控制tr的显示与隐藏 最开始写法是: <tr id="att" style="display:none;"> <td style="text-align:right;">附件文件:</td> <td> <div id="div_fujian"> <div class="

[Easyui - Grid]为easyui的datagrid、treegrid增加表头菜单,用于显示或隐藏列

为easyui的datagrid.treegrid增加表头菜单,用于显示或隐藏列 /** * @author 孙宇 * * @requires jQuery,EasyUI * * 为datagrid.treegrid增加表头菜单,用于显示或隐藏列,注意:冻结列不在此菜单中 */ var createGridHeaderContextMenu = function(e, field) { e.preventDefault(); var grid = $(this);/* grid本身 */ var

如何控制android系统中NavigationBar 的显示与隐藏

我们使用的大多数android手机上的Home键,返回键以及menu键都是实体触摸感应按键.如果你用Google的Nexus4或Nexus5话,你会发现它们并没有实体按键或触摸感应按键,取而代之的是在屏幕的下方加了一个小黑条,在这个黑条上有3个按钮控件,这种设置无疑使得手机的外观的设计更加简约.但我遇到身边用Nexus 4手机的人都吐槽这种设计,原因很简单:好端端的屏幕,被划出一块区域用来显示3个按钮(如下图所示):Back, Home, Recent.并且它一直用在那里占用着. 在androi

线程安全变量控制显示隐藏loading框

一.线程安全变量控制显示隐藏loading框 问题描述: 同一页面有两个异步网络请求,第一个请求开始,loading旋转,第二个请求开始loading旋转,第一个结束,loading停止旋转,可是这时第二个请求还没有结束,然后loading就结束了,于是问题就来了. 解决方案: 二.由上面问题引申出的问题: 1. #import <libkern/OSAtomic.h> 这段话是从网上copy过来的,总结了一下原子操作的作用.但是文中提到的osbase.h文件找不到.可能是因为版本升级我的li