I want to set bottom margin equal to view's/layout's height.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
//Main layout
<LinearLayout
android:id="#+id/content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
.
.
.
</LinearLayout>
//Bottom drawer layout
<LinearLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
.
.
.
</LinearLayout>
</FrameLayout>
How to add bottom margin to second child exactly of its height so that it goes out of the screen?
Is it possible through xml attribute?
You cant get height of a view in xml.
You can get height of a view dynamically by using ViewTreeObserver, then you can set the margin for that View.
Below is a way you can do dynamically:
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.layoutid);
final ViewTreeObserver vto = linearLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
//get LayoutWidth and height here
int layoutWidth = linearLayout.getWidth();
int layoutHeight = linearLayout.getHeight();
//set layout margin here
LinearLayout.LayoutParams llp = linearLayout.getLayoutParams();
llp.bottomMargin = layoutHeight;
linearLayout.setLayoutParams(llp);
//Then remove layoutChange Listener
ViewTreeObserver vto = linearLayout.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
vto.removeOnGlobalLayoutListener(this);
} else {
vto.removeGlobalOnLayoutListener(this);
}
}
});
Related
I ran into A problem while developing Android: IN the following code, I have a parent layout -A that contains textView - B with multiple lines of TextView. I can't get the true height of A because TextView only counts as one row, so how can I get the true height of A?
<LinearLayout
android:id="#+id/A"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="black"
android:textSize="12dp"
android:text="this is a text!this is a text!this is a text!this is a text!" />
</LinearLayout>
The true height of your view would not be known until it gets inflated during the run time so after the view have inflated in an activity.
To do this at run time you can attach a OnGlobalLayoutListener on the view tree as shown below.
LinearLayout layout = (LinearLayout)findViewById(R.id.YOUR VIEW ID);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
this.layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
this.layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
int width = layout.getMeasuredWidth();
int height = layout.getMeasuredHeight();
}
});
I've used BottomSheetDialogFragment in my project and I've designed it as below:
Target: I'm going to stick the bottom menu of BottomSheetDialog to bottom of the screen, in either mode collapse and expand.
So in BottomSheetDialog layout, I used RelativeLayout for parent and "layout_alignParentBottom" for menu container, As below:
<RelativeLayout 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:id="#+id/bottomSheetContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
tools:context=".MyBottomSheetDialogFragment">
<RelativeLayout
android:id="#+id/topSection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true">
....
</RelativeLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/descriptionContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/topSection">
....
</android.support.v4.widget.NestedScrollView>
<HorizontalScrollView
android:id="#+id/iconsContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
....
</HorizontalScrollView>
</RelativeLayout>
But the dialogue is as follows:
As you can see, the bottom menu is not visible at first.
Can someone help me to solve this problem?
To solve this, several things came to my mind when I tried, but I did not succeed.
But this finally solved for me by this way:
For collapse mode, I set the bottomSheetBehavior's peekHeight to 1/3 of the screen (with the following code):
View bottomSheetContainer = dialog.findViewById(R.id.bottomSheetContainer);
View parent = (View) bottomSheetContainer.getParent();
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) parent.getLayoutParams();
BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) params.getBehavior();
View inflatedView = View.inflate(getContext(), R.layout.word_details_bottom_sheet, null);
inflatedView.measure(0, 0);
int screenHeight = getActivity().getResources().getDisplayMetrics().heightPixels;
if (bottomSheetBehavior != null) {
bottomSheetBehavior.setPeekHeight(screenHeight /3);
}
So I decided to do it:
1- for collapse mode: bottomSheet container's height = bottomSheetBehavior's peekHeight
2- for expand mode: bottomSheet container's height = full screen Height
So I wrote the following code (full code):
WordDetailsBottomSheet.java
public class WordDetailsBottomSheet extends BottomSheetDialogFragment {
public WordDetailsBottomSheet() { // Required empty public constructor }
#NotNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog dialog = new BottomSheetDialog(getActivity(), 0);
dialog.setContentView(R.layout.word_details_bottom_sheet);
View bottomSheetContainer = dialog.findViewById(R.id.bottomSheetContainer);
View parent = (View) bottomSheetContainer.getParent();
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) parent.getLayoutParams();
BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) params.getBehavior();
View inflatedView = View.inflate(getContext(), R.layout.word_details_bottom_sheet, null);
inflatedView.measure(0, 0);
int screenHeight = getActivity().getResources().getDisplayMetrics().heightPixels;
int statusBarHeight = getStatusBarHeight();
if (bottomSheetBehavior != null) {
bottomSheetBehavior.setPeekHeight(screenHeight / BOTTOM_SHEET_PEEK_HEIGHT_PERCENT);
bottomSheetContainer.getLayoutParams().height = bottomSheetBehavior.getPeekHeight();
}
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View view, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_EXPANDED:
bottomSheetContainer.getLayoutParams().height = screenHeight-statusBarHeight;
break;
case BottomSheetBehavior.STATE_COLLAPSED:
bottomSheetContainer.getLayoutParams().height = bottomSheetBehavior.getPeekHeight();
break;
case BottomSheetBehavior.STATE_HIDDEN:
dismiss();
break;
default:
break;
}
}
#Override
public void onSlide(#NonNull View view, float slideOffset) {
}
});
return dialog;
}
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
}
word_details_bottom_sheet.xml
<RelativeLayout 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:id="#+id/bottomSheetContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
tools:context=".MyBottomSheetDialogFragment">
<RelativeLayout
android:id="#+id/topSection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true">
....
</RelativeLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/descriptionContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/topSection">
....
</android.support.v4.widget.NestedScrollView>
<HorizontalScrollView
android:id="#+id/iconsContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
....
</HorizontalScrollView>
</RelativeLayout>
In the xml file, things that matter are:
1- parent id (android:id="#+id/bottomSheetContainer")
2- iconsContainer align (android:layout_alignParentBottom="true")
As you can see, the bottom menu is not visible at first.
Can someone help me to solve this problem?
I'm guessing that this behavior is working perfectly and fine because you set layout_height of NestedScrollView (Center content) to wrap_content which means, it will be wrapped by the content inside.
Meanwhile;
android:layout_alignParentBottom="true"
To HorizontalScrollView (below layout) means that it will be under the other layouts which it currently is!
So, if you are trying to see if it is working fine or not, set 100dp-50dp (or a specific size which you can see when BottomSheetDialog show up) instead of wrap_content to NestedScrollView then you probably would see that the below layout with the other layouts will be visible.
Anyways, everything's in this layout looks correct and fine. As well as pictures says the truth.
I'm trying to determine the screen's width and height to use them in a fragment.
My fragment's layout has the id background.
If inside onViewCreated I use:
background = (RelativeLayout) view.findViewById(R.id.background);
background.post(new Runnable() {
#Override
public void run() {
int width = background.getMeasuredWidth();
int height = background.getMeasuredHeight();
Log.d("askj", width + "+" + height);
}
});
I get 1440+2276
but if I use:
WindowManager windowManager = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
Log.d("askj", width + "+" + height);
or other related methods I get:
1440+2560
I'm using those parameters to set a background and I can clearly see that the whole screen size is not taken if I use the second approach. I don't really want to use that Runnable() so is there any way in which I can solve this ?
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:id="#+id/background"
tools:context="com.example.home.background.HomeScreen">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/img"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textStyle="bold"
android:layout_centerInParent="true"
android:textSize="22sp"
/>
</RelativeLayout>
You can measure the background View before your activity has added it to its view hierarchy by yourself using measure method.
background = (RelativeLayout) view.findViewById(R.id.background);
background.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
int backgroundHeight = background.getMeasuredHeight();
int backgroundWidth = background.getMeasuredWidth();
In my case I measured an inflated View but it had the width and height set to match_paent.
View view = inflater.inflate(R.layout.table_field_text, null, false);
view.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
int viewHeight = view.getMeasuredHeight();
Use ViewTreeObserver like Below:
background = (RelativeLayout) view.findViewById(R.id.background);
final ViewTreeObserver vto = background.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
//get View Width and height here
int width = background.getWidth();
int height = background.getHeight();
//Call anyfunction which uses width and height here
function(width,height);
//Then remove layoutChange Listener
ViewTreeObserver vto = background.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
vto.removeOnGlobalLayoutListener(this);
} else {
vto.removeGlobalOnLayoutListener(this);
}
}
});
I can set ViewPager's height programatically by using vpTabs.getLayoutParams().height = DESIRED_SIZE; but it works only once at run time. now the question is how to set the height more than one time at runtime ?
activity_layout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/rlActivityProfile"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.my.package.ProfileActivity">
<!--MainContainer-->
<com.my.package.widget.ScrollViewX
android:id="#+id/svxUserProfile"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--Main Container-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--Header-->
<RelativeLayout
android:id="#+id/rlProfileBanner"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#color/listile_green">
<!-- SOME OTHER VIEW-->
</RelativeLayout>
<RelativeLayout
android:id="#+id/rlTabs"
android:layout_below="#id/rlProfileBanner"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--Slider-->
<android.support.v4.view.ViewPager
android:id="#+id/vpTabs"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/stlControl" />
</RelativeLayout>
</RelativeLayout>
</com.my.package.widget.ScrollViewX>
<!--Transparent toolbar-->
<include
android:id="#+id/iAppBar"
layout="#layout/app_bar" />
</RelativeLayout>
The viewPager is initialized in onCreate() of MainActivity class
ViewPager vpTabs = (ViewPager) findViewById(R.id.vpTabs);
I am changing the viewPager's height from fragment using an interface like this
//Calling from fragment
int totalHeight = titles.length * EditProfileAdapter.ROW_HEIGHT;
vpListener.onViewPagerHeightChange(totalHeight);
in MainActivity
#Override
public void onViewPagerHeightChange(int height) {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.height = height; //left, top, right, bottom
vpTabs.setLayoutParams(params);
}
NOTE: The custom widget ScrollViewX is the same ScrollView but with a Custom ScrollListener.
define new layoutParams and set your viewPager to it then change the layoutParams's height this will do the trick, don't do it directly to its original params or changes won't effect the layout more than once, you also have to make sure that the condition you are using is correct, try to use this:
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
//setting margins around imageimageview
params.height=yourHeight; //left, top, right, bottom
//adding attributes to the imageview
viewPager.setLayoutParams(params);
instead of setting it directly
ViewGroup.LayoutParams params= tabPager.getLayoutParams();
params.height = 500; //500px
params.width = 500; //500px
viewPager.requestLayout();
first, get the LayoutParams for your ViewPager then assign the height for this LayoutParams
ViewGroup.LayoutParams lp = viewPager.getLayoutParams();
lp.height = ScreenUtils.convertDpToPixel(300, getContext());
I see some questions about "ImageView"s, but I need a FrameLayout.
I have a FrameLayout, which I need its width:height = 2:1, and the width is fill_parent. There are many image views inside the frame layout, I can just set them width=fill_parent and height=fill_parent.
I don't find a way to do this, please help .
My xml code is:
<FrameLayout
android:id="#+id/cardView"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_centerInParent="true">
<ImageView
android:id="#+id/frameView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitXY"
android:src="#drawable/card_style1"
/>
</FrameLayout>
See if this is what you want:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
final FrameLayout target = (FrameLayout) findViewById(R.id.frame_id);
target.post(new Runnable() {
#Override
public void run() {
int width = target.getWidth();
int height = width / 2;
LayoutParams lp = target.getLayoutParams();
lp.height = height;
target.setLayoutParams(lp);
}
});
}