Last active
August 29, 2015 14:07
-
-
Save NikolaDespotoski/009595717408e7854efd to your computer and use it in GitHub Desktop.
FadingActionBar is great library, but it lacks ability to bind listeners to track how much ActionBarDrawable has been faded in/out.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.annotation.SuppressLint; | |
import android.app.Activity; | |
import android.content.Context; | |
import android.graphics.drawable.Drawable; | |
import android.os.Build; | |
import android.support.v7.app.ActionBarActivity; | |
import android.util.Log; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewTreeObserver; | |
import android.widget.AbsListView; | |
import android.widget.ListView; | |
import com.manuelpeinado.fadingactionbar.FadingActionBarHelper; | |
import java.lang.reflect.Field; | |
/** | |
* Created by Nikola on 10/15/2014. | |
*/ | |
public class NotifyingFadingActionBar extends FadingActionBarHelper { | |
private final Context mContext; | |
private AbsListView.OnScrollListener mInternalScrollListener; | |
private ActionBarDrawableAlphaCallback mAlphaCallback; | |
private ListView mListView; | |
private int mInitialBottom; | |
private float mPreviousRatio; | |
private boolean hasDispatchedCompleted = false; | |
private View mHeaderView; | |
private boolean isActionBarCompat = false; | |
private android.support.v7.app.ActionBar mSupportActionBar; | |
private List<AbsListView.OnScrollListener> mListeners = new ArrayList<AbsListView.OnScrollListener>(); | |
public enum ScrollDirection{ | |
DOWN, UP; | |
} | |
public interface ActionBarDrawableAlphaCallback{ | |
void onAlphaComplete(); | |
void onAlphaChanged(ScrollDirection direction, float fadingFactor); | |
} | |
public NotifyingFadingActionBar(Context c) { | |
mContext = c; | |
mPreviousRatio = 0.0f; | |
try { | |
Field scrollField = getClass().getSuperclass().getSuperclass().getDeclaredField("mOnScrollListener"); | |
scrollField.setAccessible(true); | |
mInternalScrollListener = (AbsListView.OnScrollListener)scrollField.get(this); | |
} catch (NoSuchFieldException e) { | |
e.printStackTrace(); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} | |
} | |
public NotifyingFadingActionBar headerLayoutResId(int resId){ | |
mHeaderView = LayoutInflater.from(mContext).inflate(resId, null); | |
super.headerView(mHeaderView); | |
return this; | |
} | |
@Override | |
public void initActionBar(Activity activity){ | |
checkForCompat(activity); | |
super.initActionBar(activity); | |
final View contentView = activity.findViewById(android.R.id.content); | |
ViewTreeObserver vto = contentView.getViewTreeObserver(); | |
if(vto != null && vto.isAlive()){ | |
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { | |
@Override | |
public void onGlobalLayout() { | |
removeGlobalLayoutListener(contentView, this); | |
findListView(contentView); | |
} | |
}); | |
}else{ | |
findListView(contentView); | |
} | |
} | |
public NotifyingFadingActionBar addOnScrollListener(AbsListView.OnScrollListener listener){ | |
addPartnerScrollListener(listener); | |
return this; | |
} | |
private void addPartnerScrollListener(AbsListView.OnScrollListener listener){ | |
if(!mListeners.contains(listener)){ | |
mListeners.add(listener); | |
} | |
} | |
private void notifyAllOnScrollListeners(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount){ | |
for(AbsListView.OnScrollListener listener : mListeners){ | |
listener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); | |
} | |
} | |
private void notifyAllOnScrollStateChangedListeners(AbsListView view, int scrollState){ | |
for(AbsListView.OnScrollListener listener : mListeners){ | |
listener.onScrollStateChanged(view, scrollState); | |
} | |
} | |
private void checkForCompat(Activity activity) { | |
isActionBarCompat = activity instanceof ActionBarActivity && Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB; | |
if(isActionBarCompat) { | |
mSupportActionBar = ((ActionBarActivity)activity).getSupportActionBar(); | |
} | |
} | |
private void findListView(View contentView){ | |
mListView = (ListView)contentView.findViewById(android.R.id.list); | |
mListView.setOnScrollListener(new NotifyingScrollListener()); | |
mInitialBottom = mHeaderView.getBottom(); | |
mHeaderView = (View)mHeaderView.getParent(); | |
} | |
public class NotifyingScrollListener implements AbsListView.OnScrollListener{ | |
@Override | |
public void onScrollStateChanged(AbsListView view, int scrollState) { | |
Log.i("Fader", "OnScrollStateChanged()"); | |
if(mInternalScrollListener != null){ | |
mInternalScrollListener.onScrollStateChanged(view, scrollState); | |
} | |
notifyAllOnScrollStateChangedListeners(view, scrollState); | |
} | |
@Override | |
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { | |
if(mInternalScrollListener != null){ | |
mInternalScrollListener.onScroll(view, firstVisibleItem,visibleItemCount,totalItemCount); | |
} | |
if( mHeaderView.getBottom() == mHeaderView.getBottom()/2 && !hasDispatchedCompleted){ | |
hasDispatchedCompleted = true; | |
if( mAlphaCallback != null) | |
mAlphaCallback.onAlphaComplete(); | |
}else if(mHeaderView.getBottom() > mHeaderView.getBottom()/2 ){ | |
hasDispatchedCompleted = false; | |
int scrolled = mInitialBottom - mHeaderView.getBottom(); | |
float ratio = (float) scrolled/ mInitialBottom; | |
ratio*=2; | |
dispatchRatioChanged(ratio); | |
} | |
notifyAllOnScrollListeners(view, firstVisibleItem, visibleItemCount, totalItemCount); | |
} | |
} | |
private void dispatchRatioChanged(float ratio) { | |
Log.i(TAG, "dispatchRatio() "+ratio + " old: "+mPreviousRatio); | |
if(ratio != mPreviousRatio) { | |
if( mAlphaCallback != null) | |
mAlphaCallback.onAlphaChanged(mPreviousRatio > ratio ? ScrollDirection.DOWN : ScrollDirection.UP, ratio); | |
mPreviousRatio = ratio; | |
} | |
} | |
public NotifyingFadingActionBar withCallback(ActionBarDrawableAlphaCallback callback){ | |
mAlphaCallback = callback; | |
return this; | |
} | |
@Override | |
protected void setActionBarBackgroundDrawable(Drawable drawable) { | |
if(!isActionBarCompat) | |
super.setActionBarBackgroundDrawable(drawable); | |
else | |
mSupportActionBar.setBackgroundDrawable(drawable); | |
} | |
@SuppressLint("NewApi") | |
@Override | |
protected int getActionBarHeight() { | |
return isActionBarCompat ? mSupportActionBar.getHeight() : super.getActionBarHeight(); | |
} | |
@Override | |
protected boolean isActionBarNull() { | |
return isActionBarCompat? mSupportActionBar == null : super.isActionBarNull(); | |
} | |
@SuppressWarnings("deprecation") | |
@SuppressLint("NewApi") | |
public static void removeGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener){ | |
if (Build.VERSION.SDK_INT < 16) { | |
v.getViewTreeObserver().removeGlobalOnLayoutListener(listener); | |
} else { | |
v.getViewTreeObserver().removeOnGlobalLayoutListener(listener); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment