Skip to content

Instantly share code, notes, and snippets.

@asbadve
Created February 5, 2017 07:42
Show Gist options
  • Save asbadve/944f233601e06e162ddb3285e27105e9 to your computer and use it in GitHub Desktop.
Save asbadve/944f233601e06e162ddb3285e27105e9 to your computer and use it in GitHub Desktop.
get notified when Appbarlayout is expand and hide with scrolling offset and states.
package com.ajinkyabadve.mywatchlist.util.listeners;
/**
* Copyright 2016 Ajinkya Badve
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.content.Context;
import android.graphics.Canvas;
import android.support.annotation.IntDef;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import static com.ajinkyabadve.mywatchlist.util.listeners.ControllableAppBarLayout.ToolbarChange.COLLAPSE;
import static com.ajinkyabadve.mywatchlist.util.listeners.ControllableAppBarLayout.ToolbarChange.COLLAPSE_WITH_ANIMATION;
import static com.ajinkyabadve.mywatchlist.util.listeners.ControllableAppBarLayout.ToolbarChange.EXPAND;
import static com.ajinkyabadve.mywatchlist.util.listeners.ControllableAppBarLayout.ToolbarChange.EXPAND_WITH_ANIMATION;
public class ControllableAppBarLayout extends AppBarLayout
implements AppBarLayout.OnOffsetChangedListener {
private static final String TAG = ControllableAppBarLayout.class.getSimpleName();
private AppBarLayout.Behavior mBehavior;
private WeakReference<CoordinatorLayout> mParent;
private int mQueuedChange = ToolbarChange.NONE;
private boolean mAfterFirstDraw = false;
private int state;
private OnStateChangeListener onStateChangeListener;
public ControllableAppBarLayout(Context context) {
super(context);
}
public ControllableAppBarLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!(getLayoutParams() instanceof CoordinatorLayout.LayoutParams)
|| !(getParent() instanceof CoordinatorLayout)) {
throw new IllegalStateException(
"ControllableAppBarLayout must be a direct child of CoordinatorLayout.");
}
mParent = new WeakReference<CoordinatorLayout>((CoordinatorLayout) getParent());
addOnOffsetChangedListener(this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mBehavior == null) {
mBehavior = (Behavior) ((CoordinatorLayout.LayoutParams) getLayoutParams()).getBehavior();
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (r - l > 0 && b - t > 0 && mAfterFirstDraw && mQueuedChange != ToolbarChange.NONE) {
analyzeQueuedChange();
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!mAfterFirstDraw) {
mAfterFirstDraw = true;
if (mQueuedChange != ToolbarChange.NONE) {
analyzeQueuedChange();
}
}
}
private synchronized void analyzeQueuedChange() {
switch (mQueuedChange) {
case COLLAPSE:
performCollapsingWithoutAnimation();
break;
case COLLAPSE_WITH_ANIMATION:
performCollapsingWithAnimation();
break;
case EXPAND:
performExpandingWithoutAnimation();
break;
case EXPAND_WITH_ANIMATION:
performExpandingWithAnimation();
break;
}
mQueuedChange = ToolbarChange.NONE;
}
public void collapseToolbar() {
collapseToolbar(false);
}
public void collapseToolbar(boolean withAnimation) {
mQueuedChange = withAnimation ? COLLAPSE_WITH_ANIMATION : COLLAPSE;
requestLayout();
}
public void expandToolbar() {
expandToolbar(false);
}
public void expandToolbar(boolean withAnimation) {
mQueuedChange = withAnimation ? EXPAND_WITH_ANIMATION : EXPAND;
requestLayout();
}
private void performCollapsingWithoutAnimation() {
if (mParent.get() != null) {
mBehavior.onNestedPreScroll(mParent.get(), this, null, 0, getHeight(), new int[]{0, 0});
}
}
private void performCollapsingWithAnimation() {
if (mParent.get() != null) {
mBehavior.onNestedFling(mParent.get(), this, null, 0, getHeight(), true);
}
}
private void performExpandingWithoutAnimation() {
if (mParent.get() != null) {
mBehavior.setTopAndBottomOffset(0);
}
}
private void performExpandingWithAnimation() {
if (mParent.get() != null) {
mBehavior.onNestedFling(mParent.get(), this, null, 0, -getHeight() * 5, false);
}
}
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
if (i == 0) {
if (onStateChangeListener != null && state != State.EXPANDED) {
onStateChangeListener.onStateChange(State.EXPANDED, i);
}
state = State.EXPANDED;
} else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
if (onStateChangeListener != null && state != State.COLLAPSED) {
onStateChangeListener.onStateChange(State.COLLAPSED, i);
}
state = State.COLLAPSED;
} else {
if (onStateChangeListener != null && state != State.IDLE) {
onStateChangeListener.onStateChange(State.IDLE, i);
}
state = State.IDLE;
}
}
public void setOnStateChangeListener(OnStateChangeListener listener) {
this.onStateChangeListener = listener;
}
@State
public int getState() {
return state;
}
public interface OnStateChangeListener {
void onStateChange(@State int toolbarChange, int offset);
}
@IntDef({State.COLLAPSED, State.EXPANDED, State.IDLE})
@Retention(RetentionPolicy.SOURCE)
public @interface State {
int COLLAPSED = 0;
int EXPANDED = 1;
int IDLE = 2;
}
@IntDef({ToolbarChange.COLLAPSE, ToolbarChange.COLLAPSE_WITH_ANIMATION, ToolbarChange.EXPAND, ToolbarChange.EXPAND_WITH_ANIMATION, ToolbarChange.NONE})
@Retention(RetentionPolicy.SOURCE)
@interface ToolbarChange {
int COLLAPSE = 3;
int COLLAPSE_WITH_ANIMATION = 4;
int EXPAND = 5;
int EXPAND_WITH_ANIMATION = 6;
int NONE = 7;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment