Set Top Padding affects Bottom Margin of a View - android

This is bottom margin:
#Override
protected void directionDownScrolling(View recyclerView) {
MarginLayoutParams params = (MarginLayoutParams) recyclerView.getLayoutParams();
params.setMargins(0, 0, 0,
(int) recyclerView.getContext().getResources().getDimension(R.dimen.dimen_recycler_view_spacing));
mHandler.postDelayed(() -> recyclerView.setLayoutParams(params), 250);
}
And Top Padding :
#Override
protected void directionDownScrolling(View recyclerView) {
// Calculate ActionBar height
TypedValue tv = new TypedValue();
int actionBarHeight = recyclerView.getContext().getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true) ?
TypedValue.complexToDimensionPixelSize(tv.data, recyclerView.getContext().getResources().getDisplayMetrics()) :
(int) recyclerView.getContext().getResources().getDimension(R.dimen.dimen_recycler_view_spacing);
recyclerView.setPadding(0, actionBarHeight, 0, 0);
}
As you see top padding applies without no delay, but I expect bottom margin appears after 250ms,
but as soon as top padding applies, bottom margin appears as well. Why and how to fix it?

You're getting the layout parameters from recyclerView:
MarginLayoutParams params = (MarginLayoutParams) recyclerView.getLayoutParams();
Then you setup the margins directly on it:
params.setMargins(0, 0, 0,
(int) recyclerView.getContext().getResources().getDimension(R.dimen.dimen_recycler_view_spacing));
So the delayed message doesn't do anything:
mHandler.postDelayed(() -> recyclerView.setLayoutParams(params), 250);
This would make a difference if you'd set the layout params to some other instance. Instead call setMargins delayed:
#Override
protected void directionDownScrolling(View recyclerView) {
MarginLayoutParams params = (MarginLayoutParams) recyclerView.getLayoutParams();
int marginBottom = (int) recyclerView.getContext().getResources().getDimension(R.dimen.dimen_recycler_view_spacing));
mHandler.postDelayed(() -> {
params.setMargins(0, 0, 0, marginBottom);
recyclerView.requestLayout();
}, 250);
}

Related

How to get heights of a transparent softkeys bar and transparent status bar?

I have an activity containing a RecyclerView and both transparent status bar (the one containing wifi signal, etc...) and softkeys bar. Of course the number of items in the RecyclerView is undefined and i need the first one to have the standard top margin plus the status bar height, and the last one the standard bottom margin plus the height of the softkeys bar. This is needed because otherwise i'll get the first and the last items partially covered by the bars when the scroll is at the top or at the bottom respectively.
Here a sample code of how i'm handling the margins programmatically:
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
topSpace = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
bottomSpace = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
standardSpace = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
topSpace.setMargins( (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, metrics),
(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8 + 24, metrics),
(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, metrics),
(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, metrics));
bottomSpace.setMargins( (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, metrics),
(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, metrics),
(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, metrics),
(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8 + 56, metrics) +
getSoftkeysHeight(activity));
standardSpace.setMargins((int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, metrics),
(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, metrics),
(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, metrics),
(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, metrics));
I'm trying to use those answers but they seems not helping me because the drawable surface of the screen is indeed the whole screen...
You can use RecyclerView.ItemDecoration to modify the margins of the specific items.
Create a class that extends RecyclerView.ItemDecoration :
public static class SimpleItemDecorator extends RecyclerView.ItemDecoration {
private int regularMargin;
private int lastPosition;
private int statusBarHeight;
private int navigationBarHeight;
public SimpleItemDecorator(Activity activity, int recyclerViewItemsCount) {
// get the regular margin
regularMargin = activity.getResources().getDimensionPixelSize(R.dimen.regularMargin);
// determine the last position
lastPosition = recyclerViewItemsCount - 1;
// get the height of the status bar
final Rect rectangle = new Rect();
final Window window = activity.getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
statusBarHeight = rectangle.top;
// get the height of the navigation bar
final int redId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
navigationBarHeight = (redId > 0) ? resources.getDimensionPixelSize(resId) : 0;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
// modify the margins
final int position = parent.getChildAdapterPosition(view);
if (position == 0) {
outRect.top = statusBarHeight + regularMargin;
} else if (position == lastPosition) {
outRect.bottom = navigationBar + regularMargin;
}
}
}
Add the created ItemDecorator to the RecyclerView :
final int recyclerViewItemsCount = 6;
final SimpleItemDecorator itemDecorator = new SimpleItemDecorator(this, recyclerViewItemsCount);
recyclerView.addItemDecorator(itemDecorator);

Toolbar height from top for all android verison

i want to show one ui below toolbar but problem is say my toolbar size is 50dp and if i say my layout margin from top 50 then for some android version its working . i think above api 22 we also need status_bar_height which includes in toollbar height .
what is the best way to get toolbar height so that i can show view above that toolbar . i am showing one overlay screen with transparent
int statusBar = getStatusBarHeight();
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
layoutParams.setMargins(0, (statusBar + 50), 0, 0);
MainRel.setLayoutParams(layoutParams);
MainRel.setVisibility(View.VISIBLE);
}
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
Use this generic code. Override the OnWindowFocusChanged
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
int toolbarHeight = toolbar.getHeight();
int statusBar = getStatusBarHeight();
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
layoutParams.setMargins(0, (statusBar + toolbarHeight), 0, 0);//you can use the toolbar height you got here.
MainRel.setLayoutParams(layoutParams);
MainRel.setVisibility(View.VISIBLE);
}

Android - Change left margin using animation

I am changing the left margin of an image view in the following manner :
ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) image.getLayoutParams ();
layoutParams.leftMargin = VALUE;
image.setLayoutParams ( layoutParams );
I would like the change in margin to apply with animation. Any clues ?
What I tried :
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat ( image , "x" , VALUE);
objectAnimator.start();
This works perfectly, as the image is moved to the specified X value with animation, HOWEVER the value of layoutParams.leftMargin remains unchanged !! So I cannot use this method, because if I try to change the value of layoutParams.leftMargin to 100 after using the objectAnimator with the value 100, the value applied is not correct ( 200 is applied instead of 100, the effect if the objectAnimator remains eventhough I am setting the left margin in the following manner :
layoutParams.leftMargin = 100;
Use Animation class, not ObjectAnimator.
final int newLeftMargin = <some value>;
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
LayoutParams params = yourView.getLayoutParams();
params.leftMargin = (int)(newLeftMargin * interpolatedTime);
yourView.setLayoutParams(params);
}
};
a.setDuration(500); // in ms
yourView.startAnimation(a);
Please note that you should use correct LayoutParams class i.e. if your view is the child of LinearLayout then params should be LinearLayout.LayoutParams
I came by this question, but I couldn't use it because I want to animate the margin from a negative value to 0, so I used valueAnimater base on user1991679 answer:
final View animatedView = view.findViewById(R.id.animatedView);
final LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) animatedView.getLayoutParams();
ValueAnimator animator = ValueAnimator.ofInt(params.bottomMargin, 0);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator)
{
params.bottomMargin = (Integer) valueAnimator.getAnimatedValue();
animatedView.requestLayout();
}
});
animator.setDuration(300);
animator.start();
You must change LinearLayout.LayoutParams according to animatedView container.
Also you can use nineoldandroids for older version that don't have ValueAnimator.
The answer from user1991679 is great, but if you need to interpolate a margin from any other value but 0, you need to use it in your calculations:
ViewGroup.MarginLayoutParams params = (MarginLayoutParams) mBottomLayout.getLayoutParams();
final int bottomMarginStart = params.bottomMargin; // your start value
final int bottomMarginEnd = <your value>; // where to animate to
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
ViewGroup.MarginLayoutParams params = (MarginLayoutParams) mBottomLayout.getLayoutParams();
// interpolate the proper value
params.bottomMargin = bottomMarginStart + (int) ((bottomMarginEnd - bottomMarginStart) * interpolatedTime);
mBottomLayout.setLayoutParams(params);
}
};
a.setDuration(300);
mBottomLayout.startAnimation(a);
In my case I needed to animate an "enter the screen" animation, coming from "-48dp" to 0. Without the start value, the animation is always 0, thus jumping, not animating the view. The solution was to interpolate the offset and add it to the original value.
Nothing worked for me like I wanted so...
I needed to create ToggleMenu from -80 dp (oldLeftMargin) to 0dp.
Same with bottomMargin, etc.
Now it works:
final int oldLeftMargin = (int) getResources().getDimension(R.dimen.left_menu_button_margin_left);
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) llMeniuToggle.getLayoutParams();
params.leftMargin = oldLeftMargin + (int) ((0 - oldLeftMargin) * interpolatedTime);
llMeniuToggle.setLayoutParams(params);
}
};
a.setDuration(500);
llMeniuToggle.startAnimation(a);
You can use the following
image.animate().setDuration(durationIn).translationXBy(offsetFloat).start();
You can also add .setInterpolator(new BounceInterpolator()) to change the look of the animation.

How to place ImageButton at x, y location?

I want to place ImageButton at x, y location of my view.
The problem is that Android adds padding around image.
Because I don't know exact size of padding, I cannot place image button at exact location.
So, I want to remove padding.
How can I remove padding around image programmatically?
button.setPadding(0, 0, 0, 0) makes button width shorter and height longer than bitmap.
button.getLayoutParams().width gives minus value.
What I tried so far is like this.
protected class MyLayout extends RelativeLayout {
Bitmap img;
ImageButton button;
public MyLayout(Context context) {
button = new ImageButton(context);
img = BitmapFactory.decodeResource(getResources(), R.drawable.img);
button.setImageBitmap(img);
params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
button.setLayoutParams(params);
params.setMargins(x, y, 0, 0);
button.setBackgroundDrawable(null);
addView(button, params);
}
}
EDIT
Use this...
MarginLayoutParams marginParams = new MarginLayoutParams(image.getLayoutParams());
int left = someValue;
int top = someValue;
marginParams.setMargins(left, top, 0, 0);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
image.setLayoutParams(layoutParams);

How to set margin of ImageView using code, not xml

I want to add an unknown number of ImageView views to my layout with margin. In XML, I can use layout_margin like this:
<ImageView android:layout_margin="5dip" android:src="#drawable/image" />
There is ImageView.setPadding(), but no ImageView.setMargin(). I think it's along the lines of ImageView.setLayoutParams(LayoutParams), but not sure what to feed into that.
Does anyone know?
android.view.ViewGroup.MarginLayoutParams has a method setMargins(left, top, right, bottom). Direct subclasses are: FrameLayout.LayoutParams, LinearLayout.LayoutParams and RelativeLayout.LayoutParams.
Using e.g. LinearLayout:
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(left, top, right, bottom);
imageView.setLayoutParams(lp);
MarginLayoutParams
This sets the margins in pixels. To scale it use
context.getResources().getDisplayMetrics().density
DisplayMetrics
image = (ImageView) findViewById(R.id.imageID);
MarginLayoutParams marginParams = new MarginLayoutParams(image.getLayoutParams());
marginParams.setMargins(left_margin, top_margin, right_margin, bottom_margin);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
image.setLayoutParams(layoutParams);
All the above examples will actually REPLACE any params already present for the View, which may not be desired. The below code will just extend the existing params, without replacing them:
ImageView myImage = (ImageView) findViewById(R.id.image_view);
MarginLayoutParams marginParams = (MarginLayoutParams) image.getLayoutParams();
marginParams.setMargins(left, top, right, bottom);
Kevin's code creates redundant MarginLayoutParams object. Simpler version:
ImageView image = (ImageView) findViewById(R.id.main_image);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(image.getLayoutParams());
lp.setMargins(50, 100, 0, 0);
image.setLayoutParams(lp);
If you want to change imageview margin but leave all other margins intact.
Get MarginLayoutParameters of your image view in this case: myImageView
MarginLayoutParams marginParams = (MarginLayoutParams) myImageView.getLayoutParams();
Now just change the margin you want to change but leave the others as they are:
marginParams.setMargins(marginParams.leftMargin,
marginParams.topMargin,
150, //notice only changing right margin
marginParams.bottomMargin);
I use simply this and works great:
ImageView imageView = (ImageView) findViewById(R.id.image_id);
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) imageView.getLayoutParams();
layoutParams.setMargins(left, top, right, bottom);
imageView.setLayoutParams(layoutParams);
setMargins()'s unit is pixel not dp. If you want to set margin in dp, just inside your values/dimens.xml file create your dimensions like:
<resources>
<dimen name="right">16dp</dimen>
<dimen name="left">16dp</dimen>
</resources>
and access like:
getResources().getDimension(R.dimen.right);
If you use kotlin, this can be simplified by creating an extension function
fun View.setMarginExtensionFunction(left: Int, top: Int, right: Int, bottom: Int) {
val params = layoutParams as ViewGroup.MarginLayoutParams
params.setMargins(left, top, right, bottom)
layoutParams = params
}
Now all you need is a view, and this extension function can be used anywhere.
val imageView = findViewById(R.id.imageView)
imageView.setMarginExtensionFunction(0, 0, 0, 0)
You can use this method, in case you want to specify margins in dp:
private void addMarginsInDp(View view, int leftInDp, int topInDp, int rightInDp, int bottomInDp) {
DisplayMetrics dm = view.getResources().getDisplayMetrics();
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.setMargins(convertDpToPx(leftInDp, dm), convertDpToPx(topInDp, dm), convertDpToPx(rightInDp, dm), convertDpToPx(bottomInDp, dm));
view.setLayoutParams(lp);
}
private int convertDpToPx(int dp, DisplayMetrics displayMetrics) {
float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, displayMetrics);
return Math.round(pixels);
}
Answer from 2020 year :
dependencies {
implementation "androidx.core:core-ktx:1.2.0"
}
and cal it simply in your code
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
setMargins(5)
}
create layout dynamically and set its parameter as setmargin() will not work directly on an imageView
ImageView im;
im = (ImageView) findViewById(R.id.your_image_in_XML_by_id);
RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(im.getLayoutParams());
layout.setMargins(counter*27, 0, 0, 0);//left,right,top,bottom
im.setLayoutParams(layout);
im.setImageResource(R.drawable.yourimage)
For me this worked:
int imgCarMarginRightPx = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, definedValueInDp, res.getDisplayMetrics());
MarginLayoutParams lp = (MarginLayoutParams) imgCar.getLayoutParams();
lp.setMargins(0,0,imgCarMarginRightPx,0);
imgCar.setLayoutParams(lp);
sample code is here ,its very easy
LayoutParams params1 = (LayoutParams)twoLetter.getLayoutParams();//twoletter-imageview
params1.height = 70;
params1.setMargins(0, 210, 0, 0);//top margin -210 here
twoLetter.setLayoutParams(params1);//setting layout params
twoLetter.setImageResource(R.drawable.oo);
In Kotlin you can write it in more pleasant way
myView.layoutParams = LinearLayout.LayoutParams(
RadioGroup.LayoutParams.MATCH_PARENT, RadioGroup.LayoutParams.WRAP_CONTENT
).apply {
setMargins(12, 12, 12, 12)
}
Using a method similar to this might save you some headaches in some situations.
If you have two passes of programmatical tinkering with margins it is safer to check if there are already some layoutParams set. If there are some margins already one should increase them and not replace them:
public void addMargins(View v, int left, int top, int right, int bottom) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) v.getLayoutParams();
if (params == null)
params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
int oldLeft = params.leftMargin;
int oldTop = params.topMargin;
int oldRight = params.rightMargin;
int oldBottom = params.bottomMargin;
params.setMargins(oldLeft + left, oldTop + top, oldRight + right, oldBottom + bottom);
v.setLayoutParams(params);
}
Here is an example to add 8px Margin on left, top, right, bottom.
ImageView imageView = new ImageView(getApplicationContext());
ViewGroup.MarginLayoutParams marginLayoutParams = new ViewGroup.MarginLayoutParams(
ViewGroup.MarginLayoutParams.MATCH_PARENT,
ViewGroup.MarginLayoutParams.WRAP_CONTENT
);
marginLayoutParams.setMargins(8, 8, 8, 8);
imageView.setLayoutParams(marginLayoutParams);
We can create Linear LayoutParams & use resources.getDimensionPixelSize for dp value.
val mContext = parent.context
val mImageView = AppCompatImageView(mContext)
mImageView.setBackgroundResource(R.drawable.payment_method_selector)
val height = mContext.resources.getDimensionPixelSize(R.dimen.payment_logo_height)
val width = mContext.resources.getDimensionPixelSize(R.dimen.payment_logo_width)
val padding = mContext.resources.getDimensionPixelSize(R.dimen.spacing_small_tiny)
val margin = mContext.resources.getDimensionPixelSize(R.dimen.spacing_small)
mImageView.layoutParams = LinearLayout.LayoutParams(width, height).apply {
setMargins(margin, margin, 0, 0)
}
mImageView.setPadding(padding, padding, padding, padding)

Categories

Resources