Android GridView 添加 HeadView

Stella981
• 阅读 661
package com.example.test;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.GridView;
import android.widget.LinearLayout;

public class HeadGridView extends LinearLayout{
    private static final String TAG = HeadGridView.class.getSimpleName();
    private LinearLayout mHeadLayout;
    private GridView mGridView;
    private int mHeadHeight;
    private boolean mIsBeingDragged;
    private float mLastMotionY;
    private float mTouchSlop;
    private boolean mGridViewFocused = true;
    private State mState = State.getDefaultMode();

    public HeadGridView(Context context) {
        this(context, null);
    }

    public HeadGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initContentView(context);
    }
    
    private void initContentView(Context context) {
        ViewConfiguration config = ViewConfiguration.get(context);
        mTouchSlop = config.getScaledTouchSlop();
        setOrientation(VERTICAL);
        GridView gridView = new GridView(context);
        LayoutParams gridParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        gridView.setNumColumns(2);
        gridView.setLayoutParams(gridParams);
        mGridView = gridView;
        initGridView(gridView);
        addView(gridView);
        
        LinearLayout headLayout = new LinearLayout(context);
        LayoutParams headParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
        headLayout.setLayoutParams(headParams);
        mHeadLayout = headLayout;
        initHead(headLayout);
        addView(headLayout,0);
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        int gridWidthSpec = MeasureSpec.makeMeasureSpec(parentWidth, MeasureSpec.EXACTLY);
        int gridHeightSpec = MeasureSpec.makeMeasureSpec(parentHeight, MeasureSpec.EXACTLY);
        mGridView.measure(gridWidthSpec, gridHeightSpec);
        setMeasuredDimension(parentWidth, parentHeight);
    }
    
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        mHeadHeight = getChildAt(0).getMeasuredHeight();
    }
    
    protected void initGridView(GridView gridView) {
        
    }

    protected void initHead(LinearLayout headLayout) {

    }
    
    @Override
    public final boolean onInterceptTouchEvent(MotionEvent event) {
        Log.d(TAG, "currentState = "+mState+" event = "+event.getAction()+" mIsBeingDragged = "+mIsBeingDragged);
        final int action = event.getAction();
        
        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
            mIsBeingDragged = false;
            return false;
        }

        if (mIsBeingDragged) {
            return true;
        }

        switch (action) {
            case MotionEvent.ACTION_MOVE:
                final float y = event.getY();
                final float absDiff = Math.abs(y - mLastMotionY);;

                if (absDiff > mTouchSlop) {
                    mLastMotionY = y;
                    mIsBeingDragged = true;
                    if (mState != State.Head_Visible) {
                        mGridViewFocused = false;
                    }
                }
                break;
            case MotionEvent.ACTION_DOWN:
                mLastMotionY = event.getY();
                mIsBeingDragged = false;
                break;
            default:
                break;
        }
        return mIsBeingDragged;
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        
        if (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) {
            return false;
        }
        
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE: {
                if (mIsBeingDragged) {
                    pullEvent(event);
                    return true;
                }
                break;
            }
            case MotionEvent.ACTION_DOWN: 
                mLastMotionY = event.getY();
                return true;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP: 
                if (mIsBeingDragged) {
                    mIsBeingDragged = false;
                }
                return true;
        }
        return false;
    }
    
    private void dispatchDownToGridView(MotionEvent e, float downY) {
        int action = e.getAction();
        MotionEvent de = MotionEvent.obtain(e);
        de.setLocation(de.getX(), downY);
        de.setAction(MotionEvent.ACTION_DOWN);
        mGridView.dispatchTouchEvent(de);
        e.setAction(action);
    }
    
    private void pullEvent(MotionEvent e) {
        if (!mGridViewFocused) {
            dispatchDownToGridView(e, mLastMotionY);
            mGridViewFocused = true;
        }
        
        float y = e.getY();
        int scrollValue = Math.round(mLastMotionY - y);
        if (mState == State.Bottom_Top) {
            if (scrollValue > 0){
                if (mState == State.Bottom_Top) {
                    dispatchDownToGridView(e, mLastMotionY);
                }
                mGridView.dispatchTouchEvent(e);
                mState = State.Bottom_Medium;
            } else {
                mState = State.Head_Visible;
            }
        }
        
        if (mState.canHeadViewScroll()) {
            int currentScrollY = getScrollY();
            int maxScroolY = mHeadHeight - currentScrollY;
            if (scrollValue > 0) { //向上滑动
                if (maxScroolY < scrollValue) {
                    scrollValue = maxScroolY;
                    mState = State.Bottom_Top;
                }
                scrollBy(0, scrollValue);
            } else { //向下滑动
                if (currentScrollY > 0) {
                    if (currentScrollY < - scrollValue) {
                        scrollValue = - currentScrollY;
                    }
                    scrollBy(0, scrollValue);
                }
            }
        } else {
            mGridView.dispatchTouchEvent(e);
            if (scrollValue < 0) {
                int top = mGridView.getChildAt(0).getTop();
                if (top == 0) {
                    mState = State.Bottom_Top;
                }
            }
        }
        mLastMotionY = y;
    }
    
    public static enum State{
        Head_Visible(0x01),
        Bottom_Top(0x02),
        Bottom_Bottom(0x03),
        Bottom_Medium(0x04);
        
        private int id;
        
        private State(int id) {
            this.id = id;
        }
        
        public int getId(){
            return id;
        }
        
        public static State getDefaultMode(){
            return State.Head_Visible;
        }
        
        static State mapState(final int id) {
            for (State value : State.values()) {
                if (id == value.getId()) {
                    return value;
                }
            }
            return getDefaultMode();
        }
        
        boolean canHeadViewScroll() {
            return this == Head_Visible || this == Bottom_Top;
        }
    }
}

简单实现,目前还有些许问题,后续可参考:https://android.googlesource.com/platform/packages/apps/Gallery2/+/idea133/src/com/android/photos/views/HeaderGridView.java

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Gallery实现流畅的新闻滚动 方法复写
package com.ename.views;import android.content.Context;import android.util.AttributeSet;import android.view.KeyEvent;import android.view.MotionEvent;
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这