1. 程式人生 > >Android中實現StickyNavLayout自己的小demo

Android中實現StickyNavLayout自己的小demo

借鑑洪洋大神StickyNavLayout的demo加入自己的註解,方便以後查閱。

一.思緒整理:

1.要實現控制元件經包含的可滑動的view向上滑去使得頭部隱藏,下面包含的view固定。拿到需求的第一想法是用scrollview去做,要這樣的話可能要解決滑動的衝突的問題。呵呵這個常規的想法也沒錯就是實現有點麻煩。

2.網上百度了一下很多的大神已經實現的這種的demo,如洪洋大神的StickyNavLayout和玉剛大神的StickLayout都是很高的借鑑例子。

3.看了程式碼思路是:自定義view繼承LinearLayout,獲取子view的高度最重要是獲取要隱藏topview,之後用在寫滑動的邏輯程式碼。

圖片效果:


1.xml檔案:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/ll"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <com.example.foreveross.myapplication.view.StickyNavLayout
        android:id="@+id/stickylayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="頭部"
            android:textSize="40dp"/>

        <TextView
            android:id="@+id/ll_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="固定部分"
            android:textSize="40dp"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/activity_recycleview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:divider="#ffff0000"
            android:dividerHeight="10dp">
        </android.support.v7.widget.RecyclerView>

    </com.example.foreveross.myapplication.view.StickyNavLayout>

</LinearLayout>
2.StickyNavLayout.java:
package com.example.foreveross.myapplication.view;

import android.content.Context;
import android.support.v4.view.NestedScrollingParent;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.OverScroller;

import com.example.foreveross.myapplication.R;


public class StickyNavLayout extends LinearLayout implements NestedScrollingParent
{

    @Override
    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes)
    {
        return true;
    }

    @Override
    public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes)
    {
    }

    @Override
    public void onStopNestedScroll(View target)
    {
    }

    @Override
    public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed)
    {
    }

    @Override
    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed)
    {
        //進行頭部view是否隱藏的判斷
        boolean hiddenTop = dy > 0 && getScrollY() < mTopViewHeight;
        boolean showTop = dy < 0 && getScrollY() >= 0 && !ViewCompat.canScrollVertically(target, -1);

        if (hiddenTop || showTop)
        {
            scrollBy(0, dy);
            consumed[1] = dy;
        }
    }

    @Override
    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed)
    {
        return false;
    }

    @Override
    public boolean onNestedPreFling(View target, float velocityX, float velocityY)
    {
        //down - //up+
        if (getScrollY() >= mTopViewHeight) return false;
        fling((int) velocityY);
        return true;
    }

    @Override
    public int getNestedScrollAxes()
    {
        return 0;
    }

    private View mTop;
    private View mNav;
    private RecyclerView mRecyclerView;

    private int mTopViewHeight;             //頂部view滾動的高度

    private OverScroller mScroller;
    private VelocityTracker mVelocityTracker;           //速度
    private int mTouchSlop;
    private int mMaximumVelocity, mMinimumVelocity;

    private float mLastY;
    private boolean mDragging;

    public StickyNavLayout(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        setOrientation(LinearLayout.VERTICAL);

        mScroller = new OverScroller(context);
        //getScaledTouchSlop是一個距離,表示滑動的時候,手的移動要大於這個距離才開始移動控制元件。
        // 如果小於這個距離就不觸發移動控制元件
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

        mMaximumVelocity = ViewConfiguration.get(context)
                .getScaledMaximumFlingVelocity();
        mMinimumVelocity = ViewConfiguration.get(context)
                .getScaledMinimumFlingVelocity();

    }

    private void initVelocityTrackerIfNotExists()
    {
        if (mVelocityTracker == null)
        {
            mVelocityTracker = VelocityTracker.obtain();
        }
    }

    private void recycleVelocityTracker()
    {
        if (mVelocityTracker != null)
        {
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }

    /**
     * 當viewgroup填充完成後執行的
     */
    @Override
    protected void onFinishInflate()
    {
        super.onFinishInflate();
        mTop = findViewById(R.id.tv);           //可隱藏的頭部
        mNav = findViewById(R.id.ll_tv);         //滑動上去可固定的
        View view = findViewById(R.id.activity_recycleview);       //listview
        mRecyclerView = (RecyclerView) view;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //獲取第一個子view把測量模式設為UNSPECIFIED
        getChildAt(0).measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        //獲取RecyclerView的高度並設定高度
        ViewGroup.LayoutParams params = mRecyclerView.getLayoutParams();
        params.height = getMeasuredHeight() - mNav.getMeasuredHeight();
        //最終的測量設定StickyNavLayout的高度
        setMeasuredDimension(getMeasuredWidth(), mTop.getMeasuredHeight() + mNav.getMeasuredHeight() + mRecyclerView.getMeasuredHeight());

    }

    /**
     * 當view的大小改變時呼叫
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);
        mTopViewHeight = mTop.getMeasuredHeight();
    }


    public void fling(int velocityY)
    {
        mScroller.fling(0, getScrollY(), 0, velocityY, 0, 0, 0, mTopViewHeight);
        invalidate();
    }

    /**
     * 滾動到位置的設定
     * @param x
     * @param y
     */
    @Override
    public void scrollTo(int x, int y)
    {
        if (y < 0)
        {
            y = 0;
        }
        if (y > mTopViewHeight)
        {
            y = mTopViewHeight;
        }
        if (y != getScrollY())
        {
            super.scrollTo(x, y);
        }
    }

    @Override
    public void computeScroll()
    {
        if (mScroller.computeScrollOffset())
        {
            scrollTo(0, mScroller.getCurrY());
            invalidate();
        }
    }
}
程式碼下載
感悟總結:

一個星期不知不覺就過了,生活就是一樣白駒過隙一般。當自己全身心的投入到一件事情當中時雖然痛苦和折磨是伴隨其中的,思想的反覆掙扎,達不到預期的心情低落;但當全然豁然開朗時卻把一切陰霾吹得煙消雲散。

個人堅持和外部的壓力,雜糅成一團亂碼。就像BUG一樣出現得不知所以然,而只有是越挫越勇之後的靜下心來的梳理思緒才能理順BUG的出處。

一個需求網上大神雖然有類似的demo可借鑑,而自己卻急於實現而不去吸收理解。只求快速地實現功能。這是丟了西瓜揀芝麻的事,使得自己精髓沒學到卻出現一大堆bug,

以後切記著這好高騖遠的想法,踏踏實實去消化吸收。

相關推薦

Android實現StickyNavLayout自己demo

借鑑洪洋大神StickyNavLayout的demo加入自己的註解,方便以後查閱。 一.思緒整理: 1.要實現控制元件經包含的可滑動的view向上滑去使得頭部隱藏,下面包含的view固定。拿到需求的第一想法是用scrollview去做,要這樣的話可能要解決滑動的衝突的問題。

Android探索之旅(第十四篇)Android實現炫酷效果的Demo(持續收錄......)

浪起來!使用 drawBitmapMesh 實現模擬水波紋效果 簡書傳送門 三十秒實現QQ首頁動畫特效 BMoveView為RadioGroup新增移動的特

Android實現陰影效果

sta 技術 wid 語言 mat floating 大表 ado sch 在Android L推出後,Google提出了全新的設計語言:材質設計。其中很重要的一點就是陰影效果的使用,你可以為每一個View設置一個elevation值,相當於除了x、y之外的z值,z值決定

android實現毛筆效果(View 畫圖)

方法 繪畫 object android中 validate 滑動 一個 lineto 效果 近期有一個項目設計一個APP實現通過觸摸屏實現毛筆寫字效果。傳統的繪畫板程序直接通過Path的moveTo和LineTo便可實現簡單的線條繪畫程序。然而要達到毛筆的筆鋒效果

Android 實現隊列方式處理優先級信息

div fragment als eth lean @override 需要 一個 原理 需求:當界面在處理消息A時,突然接收到消息B,需要立馬顯示B的信息,然後再繼續顯示消息A,或者接收到消息C,再顯示完消息A後再顯示消息C; 原理很簡單 在一個輪詢中,查詢消息列表中的元

Android實現一個簡易的Http服務器

.get json data ESS public 瀏覽器 顯示 getmethod blank 最近遇到一個需求需要在App中創建一個Http服務器供供瀏覽器調用,用了下開源的微型Htpp服務器框架:NanoHttpd,項目地址:https://github.com/Na

Android實現短音訊和震動的一些總結

好長時間沒有寫部落格了,因為最近事情比較多。所以好長時間沒有寫部落格了。堅持是一件很辛苦的事情。但還需要努力。。。好了,閒話不扯了。因為最近專案中用到了相應的短音訊和震動的功能,所以這裡總結一下相應的內容! 本文知識點: 音訊中的一些知識和常用的API介紹;

Android實現藍芽錄放音

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android實現震動的方法

實現手機震動其實很簡單,手機震動使用是Vibrator類,然後震動也是需要許可權的,在使用之前在AndroidManifest.xml檔案中新增 <uses-permission android:name="android.permission.VIBRATE"/>

android實現CardView

android在 5.0中添加了陰影效果主要通過CardView來實現,在低版本中通過android.support.v7.widget.CardView來實現。 <RelativeLayout xmlns:android="http://schemas.android.com/a

android實現內容搜尋

在編寫android搜尋程式碼的時候,如何去實現搜尋功能,考慮中的有兩種: 自定義搜尋方法:     1.自定義搜尋輸入框,搜尋圖示,搜尋按鈕     2.自定義語音輸入方法     3.自定義常用熱詞內容、樣式     4.自定義瀏覽記錄內容和樣式     5

JAVA實現截圖Demo

閒的沒事,寫個從書上看到的一個小例子,java獲取電腦螢幕內容,類似於qq截圖吧。直接上程式碼,都有註釋比較簡單。 public class ScreenPhoto { public static void main(String[] args) throws AWTException, IO

Android實現tabLayout佈局

1.佈局檔案 <android.support.design.widget.TabLayout android:id="@+id/tab" android:layout_width=“match_parent” android:layout_height=

Android實現延時執行操作的幾種方法

在Android開發中我們可能會有延時執行某個操作的需求,例如我們啟動應用的時候,一開始呈現的是一個引導頁面,過了兩三秒後,會自動跳轉到主介面。這就是一個延時操作。  下面是實現延時執行操作的幾種方法: 1.使用執行緒的休眠實現延時操作    new Thread() {

Android實現靜態的預設安裝和解除安裝應用

                最近好長時間都沒有寫blog了,主要是因為最近工作上的事以及下載Android原始碼的事耽誤的(下載原始碼這件事會在後續的blog中寫道,這個真的很有意義呀~~),那麼今天來寫點什麼呢?主要的靈感來自於早上看新聞看到一篇文章說有一款應用在後臺中解除安裝使用者手機中的所有瀏覽器的

Android實現「類方法指令抽取方式」加固方案原理解析

一、前言Android中加固方案一直在進步,因為新的加固方案出來就會被人無情的破解脫殼了,從第一代加固方案落地加密dex檔案,第二代加固方案不落地加密dex檔案,在到第三代加固方案類方法抽取,以後後面的

Android實現多Tab頁應用

Android上的多Tab是一個什麼效果?如果圖片看不懂的話,但是使用過Android的微部落格戶端,那也很清晰了,就是那個樣子。 但是在Android API V4版本之後,TabActivity被廢棄了不推薦使用,被替換為Fragment, FragmentActivity了,使用新的API

golang 實現檔案傳輸demo

    獲取檔案資訊需要用到os. Stat介面,傳送檔案前開啟接收者(服務端),啟動客戶端先發送檔名給接收者,接收者收到檔名返回確認資訊"ok",才讀取本地檔案 傳送給接收者。 傳送者: package main import ( "fmt" "io

Unity5+Vuforia實現一個ARDemo (1)

前言 上學期擔任了導師一門選修課的TA,課程是關於VR和AR的,所以就設計了一個簡單的AR小Demo實驗,其實都是網路上用Unity+Vuforia做的AR效果,這裡只是整理歸納一下步驟而已,分為兩部分,第一部分是顯示模型,第二部分是對模型進行簡單操作。由於這

Android實現多條目載入

先寫幾個佈局檔案 public class MyAdapter extends BaseAdapter { private Context mcontext; private List<JsonBean.ResultBean.DataBean> li