Skip to content

Instantly share code, notes, and snippets.

@homj
Last active January 26, 2020 21:21
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save homj/af15defdc7e7a67dd9c4 to your computer and use it in GitHub Desktop.
Save homj/af15defdc7e7a67dd9c4 to your computer and use it in GitHub Desktop.
A utility-class providing methods to easily align a CardView in a layout by using margins; modifications pulled from https://gist.github.com/flore2003/943ef5e9fe316f903262
package de.twoid.widget.util;
/*
* Copyright 2015 Johannes Homeier, Florian Reifschneider
*
* 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.
*
*
* Modified by Florian Reifschneider <flore2003@googlemail.com> to use the padding
* calculation from the support library.
*/
import android.support.v7.widget.CardView;
import android.view.ViewGroup;
/**
* A utility-class providing methods to easily align a {@link android.support.v7.widget.CardView} in a layout by using margins
*/
public class CardViewUtils {
// used to calculate content padding
final static double COS_45 = Math.cos(Math.toRadians(45));
final static float SHADOW_MULTIPLIER = 1.5f;
/**
* Computes the compatPadding for the passed {@link CardView}
*
* @param cardView the CardView to generate the compatPadding from
* @return a array of integers with paddingLeft (position 0), paddingTop (position 1) ,paddingRight (position 2) and paddingBottom (position 3)
*/
public static int[] getCompatPadding(CardView cardView) {
int[] compatPadding = new int[4];
float elevation = cardView.getMaxCardElevation();
float radius = cardView.getRadius();
boolean addPaddingForCorners = cardView.getPreventCornerOverlap();
compatPadding[0] = compatPadding[2] = (int) Math.ceil(calculateHorizontalPadding(elevation, radius,
addPaddingForCorners));
compatPadding[1] = compatPadding[3] = (int) Math.ceil(calculateVerticalPadding(elevation, radius,
addPaddingForCorners));
return compatPadding;
}
private static float calculateVerticalPadding(float maxShadowSize, float cornerRadius,
boolean addPaddingForCorners) {
if (addPaddingForCorners) {
return (float) (maxShadowSize * SHADOW_MULTIPLIER + (1 - COS_45) * cornerRadius);
} else {
return maxShadowSize * SHADOW_MULTIPLIER;
}
}
private static float calculateHorizontalPadding(float maxShadowSize, float cornerRadius,
boolean addPaddingForCorners) {
if (addPaddingForCorners) {
return (float) (maxShadowSize + (1 - COS_45) * cornerRadius);
} else {
return maxShadowSize;
}
}
/**
* Sets a compatMargin to the cardView so that the sum of compatMargin and compatPadding on either side sum up to the passed compatMargin for that side
*
* @param child the CardView to set the compatMargin to
* @param compatMarginLeft the compatMargin from the left of the cardviews content
* @param compatMarginTop the compatMargin from the top of the cardviews content
* @param compatMarginRight the compatMargin from the right of the cardviews content
* @param compatMarginBottom the compatMargin from the bottom of the cardviews content
* @param allowNegativeMargin if true, the compatMargins can be negative (in case the computed compatPadding of the cardView is bigger than the compatMargin on the same side; otherwise, the compatMargin will be clamped to 0
*/
public static void setCompatMargin(CardView child, int compatMarginLeft, int compatMarginTop, int compatMarginRight, int compatMarginBottom, boolean allowNegativeMargin) {
int[] compatPadding = getCompatPadding(child);
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) child.getLayoutParams();
params.leftMargin = allowNegativeMargin ? compatMarginLeft - compatPadding[0] : Math.max(0, compatMarginLeft - compatPadding[0]);
params.topMargin = allowNegativeMargin ? compatMarginTop - compatPadding[1] : Math.max(0, compatMarginTop - compatPadding[1]);
params.rightMargin = allowNegativeMargin ? compatMarginRight - compatPadding[2] : Math.max(0, compatMarginRight - compatPadding[2]);
params.bottomMargin = allowNegativeMargin ? compatMarginBottom - compatPadding[3] : Math.max(0, compatMarginBottom - compatPadding[3]);
}
/**
* Sets a compatMargin to the cardView so that the sum of compatMargin and compatPadding on either side sum up to the passed compatMargin for that side;
* If the resulting margin for a side is negative, it will be set to 0.
*
* @param child the CardView to set the compatMargin to
* @param compatMarginLeft the compatMargin from the left of the cardviews content
* @param compatMarginTop the compatMargin from the top of the cardviews content
* @param compatMarginRight the compatMargin from the right of the cardviews content
* @param compatMarginBottom the compatMargin from the bottom of the cardviews content
*/
public static void setCompatMargin(CardView child, int compatMarginLeft, int compatMarginTop, int compatMarginRight, int compatMarginBottom) {
setCompatMargin(child, compatMarginLeft, compatMarginTop, compatMarginRight, compatMarginBottom, false);
}
/**
* Sets a compatMargin to the cardView so that the sum of compatMargin and compatPadding on either side sum up to the passed compatMargin for that side;
*
* @param child the CardView to set the compatMargin to
* @param compatMarginLeftRight the compatMargin from the left and right of the cardviews content
* @param compatMarginTopBottom the compatMargin from the top and bottom of the cardviews content
* @param allowNegativeMargin if true, the compatMargins can be negative (in case the computed compatPadding of the cardView is bigger than the compatMargin on the same side; otherwise, the compatMargin will be clamped to 0
*/
public static void setCompatMargin(CardView child, int compatMarginLeftRight, int compatMarginTopBottom, boolean allowNegativeMargin) {
setCompatMargin(child, compatMarginLeftRight, compatMarginTopBottom, compatMarginLeftRight, compatMarginTopBottom, allowNegativeMargin);
}
/**
* Sets a compatMargin to the cardView so that the sum of compatMargin and compatPadding on either side sum up to the passed compatMargin for that side;
* If the resulting margin for a side is negative, it will be set to 0.
*
* @param child the CardView to set the compatMargin to
* @param compatMarginLeftRight the compatMargin from the left and right of the cardviews content
* @param compatMarginTopBottom the compatMargin from the top and bottom of the cardviews content
*/
public static void setCompatMargin(CardView child, int compatMarginLeftRight, int compatMarginTopBottom) {
setCompatMargin(child, compatMarginLeftRight, compatMarginTopBottom, compatMarginLeftRight, compatMarginTopBottom);
}
/**
* Sets a compatMargin to the cardView so that the sum of compatMargin and compatPadding on either side sum up to the passed compatMargin for that side;
*
* @param child the CardView to set the compatMargin to
* @param compatMargin the compatMargin from the left, top, right and bottom of the cardviews content
* @param allowNegativeMargin if true, the compatMargins can be negative (in case the computed compatPadding of the cardView is bigger than the compatMargin on the same side; otherwise, the compatMargin will be clamped to 0
*/
public static void setCompatMargin(CardView child, int compatMargin, boolean allowNegativeMargin) {
setCompatMargin(child, compatMargin, compatMargin, compatMargin, compatMargin, allowNegativeMargin);
}
/**
* Sets a compatMargin to the cardView so that the sum of compatMargin and compatPadding on either side sum up to the passed compatMargin for that side;
* If the resulting margin for a side is negative, it will be set to 0.
*
* @param child the CardView to set the compatMargin to
* @param compatMargin the compatMargin from the left, top, right and bottom of the cardviews content
*/
public static void setCompatMargin(CardView child, int compatMargin) {
setCompatMargin(child, compatMargin, compatMargin, compatMargin, compatMargin);
}
/**
* Computes the dimension of the CardViews content
*
* @param cardView
* @return a array of integers with width (position 0) and height (position 1) of the CardViews content
*/
public static int[] getContentDimension(CardView cardView) {
int[] compatPadding = getCompatPadding(cardView);
return new int[]{
cardView.getWidth() - compatPadding[0] - compatPadding[2]
, cardView.getHeight() - compatPadding[1] - compatPadding[3]
};
}
}
@flore2003
Copy link

Very nice, thank you!

@flore2003
Copy link

I've forked your gist and made some slight modifications to it. you might want to check it out at https://gist.github.com/flore2003/943ef5e9fe316f903262

@homj
Copy link
Author

homj commented Jan 23, 2015

Thanks a lot! i didn't even know there was a method to get the radius... must have overlooked that method 😣

@flore2003
Copy link

I've actually taken a second look and realized that there is a little bit more to the calculation (it also depends on the preventCornerOverlap flag for instance). I've updated my gist with the exact calculation as it is implemented in the support library. I've tested it and as far as I can see, it works flawlessly now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment