I am using the AdMob Adaptive banner for my app that changes width and height accordingly to the device.
With AdMob only, the ad dimensions are ([DEVICE_WIDTH] x [50dp min]). On most devices the height changes to 60dp+.
The problem occurs with mediation partners that have banners limited to 50dp height. This is causing layout shifting from 60dp to 50dp and vice versa (depending on the ad provider) which is not recommended in AdMob policy.
Any idea on how to stop the layout shift?
XML
Fragment container
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#id/constraintLayoutAds"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/mobile_navigation" />
Ad container
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintLayoutAds"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<FrameLayout
android:id="#+id/frameLayoutAdContainerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:minHeight="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Java
Load ad
AdView adView = new AdView(ActivityMain.this);
adView.setAdSize(FindAdSize.adSize(ActivityMain.this));
frameLayoutAdContainerView.addView(adView, layoutParams);
AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);
Kotlin
Calculate AdSize
class FindAdSize : AppCompatActivity() {
companion object {
#Suppress("DEPRECATION")
#JvmStatic
fun adSize(activity: Activity): AdSize {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(
activity,
activity.resources.configuration.screenWidthDp
) else {
val display = activity.windowManager.defaultDisplay
val outMetrics = DisplayMetrics()
display.getMetrics(outMetrics)
val density = outMetrics.density
val adWidthPixels = outMetrics.widthPixels.toFloat()
val adWidth = (adWidthPixels / density).toInt()
AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(activity, adWidth)
}
}
}
}
Mediation providers in use: Meta, AppLovin, AdColony, Vungle, Tapjoy, and IronSource.
You can try the following approach to ensure that the ad container height is always equal to the height of the ad:
AdView adView = new AdView(ActivityMain.this);
adView.setAdSize(FindAdSize.adSize(ActivityMain.this));
adView.setAdUnitId("YOUR_AD_UNIT_ID");
// Set the minimum height of the ad container to 50dp
frameLayoutAdContainerView.setMinimumHeight((int) (50 * getResources().getDisplayMetrics().density));
// Set the height of the AdView to "match_parent"
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
// Center the AdView vertically within the ad container
layoutParams.gravity = Gravity.CENTER_VERTICAL;
frameLayoutAdContainerView.addView(adView, layoutParams);
AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);
With this approach, the ad container will always have a minimum height of 50dp, but the actual height of the ad will be determined by the AdView, which will fill the entire height of the ad container.
I'm thinking that setting the height of the AdView to "match_parent" might not be ideal for all devices and screen sizes, ad the available space for the ad might vary. This could be a trade-off to ensure that the ad container height is always equal to the height of the ad and avoid layout shifts.
Related
I need to set the height of the FrameLayout android:id="#+id/heart_strength according to the height of the FrameLayout android:id="#+id/heart_strength_background, whose height is set like this:
<FrameLayout
android:id="#+id/cardiogram_background_light"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="#dimen/default_screen_margin"
android:layout_marginTop="#dimen/chart_widget_margin_top"
android:layout_marginEnd="#dimen/default_screen_margin"
android:background="#drawable/chart_widget_background_light_gray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.184"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/heart_rate_diagram_background_light" />
<FrameLayout
android:id="#+id/heart_strength_background"
android:layout_width="#dimen/cardiogram_status_bar_width"
android:layout_height="0dp"
android:layout_marginEnd="#dimen/default_screen_margin"
android:background="#drawable/chart_widget_background_dark_gray"
app:layout_constraintBottom_toBottomOf="#+id/cardiogram_background_light"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/cardiogram_background_light" >
<FrameLayout
android:id="#+id/heart_strength"
android:layout_width="match_parent"
android:layout_height="0dp"
app:heartStrength="#{viewmodel.heartStrengthLiveData}"
android:background="#drawable/chart_widget_background_light_gray"
android:backgroundTint="#color/turquoise"
android:layout_gravity="bottom"/>
</FrameLayout>
When I try to get real height of heart_strength.parent layout with:
#JvmStatic
#BindingAdapter("app:heartStrength")
fun setHeartStrengthViewHeight(bar: FrameLayout, level: Int) {
val barParent = bar.parent as FrameLayout
println("bar parent height: ${barParent.layoutParams.height}")
}
I get 0. How can I know the actual height?
I have a card (cardiogram_background_light). Its height changes dynamically in %. Because of this, the maximum height of the bar located in this card also changes dynamically. Previously, I set its height as maxHeight * Value /100. But now maxHeight dynamically changes on different screen sizes and I want to know its value.
It is because the views are not drawn yet when setHeartStrengthViewHeight is called. To solve this, try the following:
#JvmStatic
#BindingAdapter("app:heartStrength")
fun setHeartStrengthViewHeight(bar: FrameLayout, level: Int) {
val barParent = bar.parent as FrameLayout
val observer : ViewTreeObserver = barParent.viewTreeObserver
observer.addOnGlobalLayoutListener(object: ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
println("bar parent height: ${barParent.height}")
barParent.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
})
}
I have a drawable that's being displayed in a layout. The drawable has default properties such as color and width. I'm creating a data class to be able to update those when the recycler view is created. The part that fills in the color in the middle is working. But I'm stuck on how to actually update the drawable width and the ImageView margins from the viewHolder.
mydrawable.xml
The layout file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/rect_outline"
android:src="#drawable/mydrawable"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</LinearLayout>
The data class
data class ImageData(
val c: String
val width: Int
val marginLeft : Int
)
MyViewHoler.kt
internal class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: ImageData) {
itemView.rect_outline.setColorFilter(Color.parseColor(item.c))
}
}
first put this into your xml image view component
android:scaleType="fitCenter"
my sugest is use scale with animation to get a good looking for the user
imageView.animate()
.scaleX(scaleValue)
.scaleY(scaleValue)
.setDuration(MOVING_ANIMATION_DURATION)
.start()
imageView.invalidate()
but you can set a new layout params like:
val l = imageView.layoutParams
l.height = value
l.width = value
imageView.layoutParams = l
you can do this way too
val params = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
params.setMargins(0, 20, 0, 40)
params.height = 1
params. width = 1
imageView.layoutParams = params
I want to set height and width for framelayout , if give values in java code using setlayoutparams its showing very small box, but in XML its showing properly.
This is my java code
FrameLayout frameLayout2= (FrameLayout) light.findViewById(R.id.frameLayout2);
ConstraintLayout.LayoutParams lp = new ConstraintLayout.LayoutParams(300, 300);
frameLayout2.setLayoutParams(lp);
this is my xml:
Note:Constraint layout is my parent
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LightPlaceFragment"
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp"
android:background="#color/colorAccent">
<FrameLayout
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintHorizontal_bias="0.882"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="#+id/l_width"
app:layout_constraintVertical_bias="0.162"
android:id="#+id/frameLayout2">
<include
android:id="#+id/other"
android:layout_width="300dp"
android:layout_height="200dp"
android:visibility="visible"
layout="#layout/sample1" />
</FrameLayout>
</android.support.constraint.ConstraintLayout>
values given in xml so its showing properly:
Result using XML
Values in given java code so its showing very smallbox
Result using Java
How can I change the framelayout width and height programatically?
Please help me.
Try this
FrameLayout frameLayout2= (FrameLayout) light.findViewById(R.id.frameLayout2);
ConstraintLayout.LayoutParams oldParams = (ConstraintLayout.LayoutParams) frameLayout2.getLayoutParams();
oldParams.width=400;
oldParams.height=500;
frameLayout2.setLayoutParams(oldParams);
OR this
FrameLayout frameLayout2= (FrameLayout) light.findViewById(R.id.frameLayout2);
ConstraintLayout.LayoutParams oldParams= new ConstraintLayout.LayoutParams(300,300);
frameLayout2.setLayoutParams(oldParams);
Happened with me as well.
After spending so much time, I got to know that on setting height and width programmatically it takes in PX (pixel) not in dp which we set in XML.
So you need to convert dimension into PX from dp first using display factor like this.
val scale: Float = resources.displayMetrics.density
val resizedInPx = (widthInDp * scale + 0.5f).toInt() // dp to px
Where widthInDp is the desired dp you want to set like 300
Usage
val params: ViewGroup.LayoutParams = yourlayout.layoutParams
params.width = (widthInDp * scale + 0.5f).toInt() // dp to px
params.height = (heightInDp * scale + 0.5f).toInt() // dp to px
layout!!.setLayoutParams(params)
Use this
FrameLayout frameLayout2= (FrameLayout) light.findViewById(R.id.frameLayout2);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(300, 300);
frameLayout2.setLayoutParams(lp);
(KOTLIN) If you need to update the width and height only, you can use the below method:
private fun resizeView(view: View) {
val size = resources.getDimension(R.dimen.view_size).toInt()
view.layoutParams.width = size
view.layoutParams.height = size
//or (but be careful because this will change all the constraints you added in the xml file)
val newLayoutParams = ConstraintLayout.LayoutParams(size, size)
view.layoutParams = newLayoutParams
}
I am using GridLayout(support) for displaying ImageViews in my application. There are 3 columns and 5 rows. The problem is that the cells in the GridLayout automatically get some space between them. I am not setting any padding or margin for the cells. Please refer to the image below. All cells are added dynamically and here is how I add these cells.
Getting Screen Width and Height:
Point size = new Point();
getWindowManager().getDefaultDisplay().getSize(size);
screenWidth = size.x;
screenHeight = size.y;
rowHeight = (int) (screenHeight * 0.2);
Adding View to GridLayout:
GridLayout.LayoutParams params = new GridLayout.LayoutParams(
getSpec(rowColumn[0]), getSpec(rowColumn[1]));
params.height = rowHeight;
if (rowColumn[1].equalsIgnoreCase("col_full")) {
params.width = (int) (screenWidth);
} else if (rowColumn[1].equalsIgnoreCase("col_two_part")) {
params.width = (int) (screenWidth * 0.6);
} else {
params.width = (int) (screenWidth * 0.3);
}
ImageButton image = (ImageButton) imageHashMap
.get(reOrderedButtonsListCopy.get(i));
image.setLayoutParams(params);
gridLayout.addView(image, params);
XML Layout:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.xx.xxx"
android:id="#+id/scrollView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<android.support.v7.widget.GridLayout
xmlns:app="http://schemas.android.com/apk/res/com.xx.xxx"
android:id="#+id/gridlayout_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp"
app:columnCount="3"
app:rowCount="5" >
</android.support.v7.widget.GridLayout>
</LinearLayout>
</ScrollView>
Current result:
The red lines show the spaces in between the cells. Also, there is some space on the left side of GridLayout. I have only given 2dp as layout_margin. Any reasons why this padding occurs?
[EDIT]
Making the following changes removed the spacings.
gridLayout = (GridLayout) findViewById(R.id.gridlayout_main);
gridLayout.setUseDefaultMargins(false);
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setRowOrderPreserved(false);
Refer to the image below.
Found the solution.
Making the following changes removed the spacings.
gridLayout = (GridLayout) findViewById(R.id.gridlayout_main);
gridLayout.setUseDefaultMargins(false);
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setRowOrderPreserved(false);
Refer to the image below.
The only solution that worked for me was to add extra columns in the GridLayout like android:columnCount="7" and then the column that needs more width set to 3 or more. The more space you want to give to that column. It then automatically reserves more space for those columns. The whole GridLayout works as a stretching thing. The columnWeight says how much a column can stretch.
<LinearLayout
android:layout_width="match_parent"
android:layout_height=" "
android:orientation="vertical" >
Here's the thing, lets say i have this LinearLayout that has a width of match_parent, so the width of the LinearLayout depends on the width of the device. What i dont know is how could i set the android:layout_height=" " value to correspond on the value of the android:layout_width="match_parent" so i could have a Square LinearLayout i know i can do this using LayoutParams but is there a way to do it on xml? Thank you guys..
First get screen width
Display mDisplay = activity.getWindowManager().getDefaultDisplay();
int width = mDisplay.getWidth();
int height = mDisplay.getHeight();
Set Size to Layout
LinearLayout layout = (LinearLayout)findViewById(R.id.LayoutID);
// Gets the layout params that will allow you to resize the layout
LayoutParams params = layout.getLayoutParams();
// Changes the height and width to the specified *pixels*
params.height = width;
params.width = width;
layout.setLayoutParams(params);
In XML:
<LinearLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:id="#+id/LayoutID"
android:orientation="vertical" >