/* * Copyright (C) 2015 The Android Open Source Project * * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. */ package io.plaidapp.util; import android.support.v4.view.ViewCompat; import android.util.Property; import android.view.View; /** * Utility helper for moving a {@link android.view.View} around using * {@link android.view.View#offsetLeftAndRight(int)} and * {@link android.view.View#offsetTopAndBottom(int)}. * <p> * Allows the setting of absolute offsets (similar to translationX/Y), in addition to relative * offsets. Reapplies offsets after a layout pass (as long as you call {@link #onViewLayout()}). * <p> * Adapted from the mDesign support library. */ public class ViewOffsetHelper { /** * Animatable property */ public static final Property<ViewOffsetHelper, Integer> OFFSET_Y = AnimUtils.createIntProperty( new AnimUtils.IntProp<ViewOffsetHelper>("topAndBottomOffset") { @Override public void set(ViewOffsetHelper viewOffsetHelper, int offset) { viewOffsetHelper.setTopAndBottomOffset(offset); } @Override public int get(ViewOffsetHelper viewOffsetHelper) { return viewOffsetHelper.getTopAndBottomOffset(); } }); private final View mView; private int mLayoutTop; private int mLayoutLeft; private int mOffsetTop; private int mOffsetLeft; public ViewOffsetHelper(View view) { mView = view; } public void onViewLayout() { // Grab the intended top & left mLayoutTop = mView.getTop(); mLayoutLeft = mView.getLeft(); // And offset it as needed updateOffsets(); } /** * Set the top and bottom offset for this {@link ViewOffsetHelper}'s view by * an absolute amount. * * @param absoluteOffset the offset in px. * @return true if the offset has changed */ public boolean setTopAndBottomOffset(int absoluteOffset) { if (mOffsetTop != absoluteOffset) { mOffsetTop = absoluteOffset; updateOffsets(); return true; } return false; } /** * Set the top and bottom offset for this {@link ViewOffsetHelper}'s view by * an relative amount. */ public void offsetTopAndBottom(int relativeOffset) { mOffsetTop += relativeOffset; updateOffsets(); } /** * Set the left and right offset for this {@link ViewOffsetHelper}'s view by * an absolute amount. * * @param absoluteOffset the offset in px. * @return true if the offset has changed */ public boolean setLeftAndRightOffset(int absoluteOffset) { if (mOffsetLeft != absoluteOffset) { mOffsetLeft = absoluteOffset; updateOffsets(); return true; } return false; } /** * Set the left and right offset for this {@link ViewOffsetHelper}'s view by * an relative amount. */ public void offsetLeftAndRight(int relativeOffset) { mOffsetLeft += relativeOffset; updateOffsets(); } public int getTopAndBottomOffset() { return mOffsetTop; } public int getLeftAndRightOffset() { return mOffsetLeft; } /** * Notify this helper that a change to the view's offsets has occurred outside of this class. */ public void resyncOffsets() { mOffsetTop = mView.getTop() - mLayoutTop; mOffsetLeft = mView.getLeft() - mLayoutLeft; } private void updateOffsets() { ViewCompat.offsetTopAndBottom(mView, mOffsetTop - (mView.getTop() - mLayoutTop)); ViewCompat.offsetLeftAndRight(mView, mOffsetLeft - (mView.getLeft() - mLayoutLeft)); } }