package org.ccci.gto.android.common.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ScrollView;

import org.ccci.gto.android.common.R;

public class AffixingScrollView extends ScrollView {
    private final static int INVALID_RESOURCE = -1;

    private int mAffixingId = INVALID_RESOURCE;
    private View mAffixingView;
    private int mAnchorId = INVALID_RESOURCE;
    private View mAnchorView;

    public AffixingScrollView(final Context context) {
        super(context);
    }

    public AffixingScrollView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        this.init(attrs);
    }

    public AffixingScrollView(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);
        this.init(attrs);
    }

    private void init(final AttributeSet attrs) {
        final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.AffixingScrollView);
        mAffixingId = a.getResourceId(R.styleable.AffixingScrollView_affixingView, INVALID_RESOURCE);
        mAnchorId = a.getResourceId(R.styleable.AffixingScrollView_anchorView, INVALID_RESOURCE);
        a.recycle();
    }

    /**
     * Attach the appropriate child view to managed during scrolling as the affixing view. This view MUST be an
     * existing child.
     *
     * @param v View to manage as the floating view
     */
    public void setAffixingView(final View v) {
        mAffixingView = v;
        updateAffixingView();
    }

    /**
     * Attach the appropriate child view to monitor during scrolling as the anchoring space for the floating view.
     * This view MUST be an existing child.
     *
     * @param v View to manage as the anchoring space
     */
    public void setAnchorView(final View v) {
        mAnchorView = v;
        updateAffixingView();
    }

    /* BEGIN lifecycle */

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (mAnchorId > 0) {
            mAnchorView = this.findViewById(mAnchorId);
            mAnchorId = INVALID_RESOURCE;
        }
        if (mAffixingId > 0) {
            mAffixingView = this.findViewById(mAffixingId);
            mAffixingId = INVALID_RESOURCE;
        }
        updateAffixingView();
    }

    @Override
    protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) {
        super.onLayout(changed, l, t, r, b);
        updateAffixingView();
    }

    @Override
    protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        updateAffixingView();
    }

    /* END lifecycle */

    private void updateAffixingView() {
        if (mAnchorView == null || mAffixingView == null) {
            return;
        }

        // is the anchor view off the screen?
        if (mAnchorView.getTop() - getScrollY() < 0) {
            // Yes, move the affixing view to the top of the visible view
            mAffixingView.offsetTopAndBottom(getScrollY() - mAffixingView.getTop());
        } else {
            // No, move the affixing view to the anchor view
            mAffixingView.offsetTopAndBottom(mAnchorView.getTop() - mAffixingView.getTop());
        }
    }
}

@@ -109,16 +109,101 @@
 dArray;%0A
+import android.support.annotation.IdRes;%0Aimport android.support.annotation.Nullable;%0A
 import a
@@ -228,16 +228,16 @@
 uteSet;%0A
-
 import a
@@ -434,16 +434,27 @@
  = -1;%0A%0A
+    @IdRes%0A
     priv
@@ -485,32 +485,46 @@
 VALID_RESOURCE;%0A
+    @Nullable%0A
     private View
@@ -539,16 +539,27 @@
 ngView;%0A
+    @IdRes%0A
     priv
@@ -592,24 +592,38 @@
 D_RESOURCE;%0A
+    @Nullable%0A
     private 

add a couple annotations to AffixingScrollView