I am trying to get the height and width of my imageview so I can scale my image down the the appropriate size but everytime I try to get the height I get the height as 0. I thought maybe it just was not measured yet so I put a onPreDrawListener on the imageview so that I know it would be measured at that time but I still get 0 so I am not sure the problem.
this is my full layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:id="#+id/content"
android:layout_above="#+id/comment_layout">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/imageView"/>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/comments"
android:background="#android:color/transparent"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/comment_layout">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/editText"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="#+id/send_button"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/send_button"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"/>
</RelativeLayout>
</RelativeLayout>
here is where I try to get the height
ViewTreeObserver obs = imageView.getViewTreeObserver();
if(obs != null){
obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
if(image != null){
imageView.getViewTreeObserver().removeOnPreDrawListener(this);
int height = imageView.getHeight(); // 0
int width = imageView.getWidth(); // 720
}
return false;
}
});
}
the width displays 720 but the height always displays 0.
putting in a hard width also has no effect
This should work with an OnGlobalLayoutListener like so
final ImageView image = new ImageView(this);
image.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
int height = image.getHeight();
}
});
This callback is invoked when the global layout state or the visibility changes
Related
I've been trying to measure the pixel dimensions of a view within a RelativeLayout that's within another RelativeLayout:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="60"
>
...
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/labels_placeholder"
android:id="#+id/player_section_layout"
>
<LinearLayout
android:id="#+id/player_section_background"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"
android:weightSum="100">
<!--The view above is what I'm trying to measure-->
<LinearLayout
android:id="#+id/player_section_background_left"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="50"
android:background="#AAAAAA"
android:orientation="horizontal" />
<LinearLayout
android:id="#+id/player_section_background_right"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="50"
android:background="#DD0000"
android:orientation="horizontal" />
</LinearLayout>
<HorizontalScrollView
android:id="#+id/player_section"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_alignTop="#id/player_section_background">
<ImageView
android:id="#+id/waveform_placeholder"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:scaleType="centerInside"
/>
</HorizontalScrollView>
</RelativeLayout>
</RelativeLayout>
I tried calling getMeasuredHeight() and getMeasuredWidth() right after referring to it in onCreateView() of the fragment:
waveformBackground = (LinearLayout)result.findViewById(R.id.player_section_background);
waveformBackground.post(new Runnable() {
#Override
public void run() {
Log.i("bckg_layout_dims", waveformBackground.getMeasuredWidth()+" "+waveformBackground.getMeasuredHeight());
}
});
And it returns 0 for both.
I did hear something about it not working before the view is being drawn, but I don't know when exactly it finishes drawing. Is it after OnCreateView, and if so, can I call it in OnActivityResult?
The problem you are facing is because the view is being drawn after you ask for the height and width. I used a ViewTreeObserver which constantly listens for changes in the views, and can access the measurements after the views has been drawn. Im not sure this is the best solution for your problem but you should look into it. Here's an example:
mTitleContainer.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int toolBarHeight = mTitle.getHeight() + mSubtitle.getHeight() + (int) TOOLBARPADDING;
if (toolBarHeight != mLastTitleHeight) {
CollapsingToolbarLayout.LayoutParams layoutParams = (CollapsingToolbarLayout.LayoutParams) mTitleToolbar.getLayoutParams();
layoutParams.height = toolBarHeight;
mTitleToolbar.setLayoutParams(layoutParams);
mLastTitleHeight = toolBarHeight;
}
}
}
);
So I've read quite a few questions on here as well as tried lots of stuff to try to get this to work. I'm either misunderstanding all of the examples I've read or am looking at the wrong stuff.
What I'm trying to do is set up a relative layout within a relative layout that contains an image view. I want to be able to have the relative layout match the size of the imageview (which I want scaled based on specific screen size) to keep a constant square size. This view will contain buttons as well.When I run the below code I get a square for the image view but the buttons are displayed on the top of the screen. So it appears to me that the imageview is properly scaling down into a square but the layout itself is still matching the overall screen size. I have an XML file set up as follows:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:id="#+id/layout_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
>
<ImageView
android:id="#+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="#drawable/bg" />
<Button
android:id="#+id/button_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button_one" />
....
</RelativeLayout>
</RelativeLayout>
Java code below:
public class MainActivity extends ActionBarActivity {
RelativeLayout layoutTwo, mainLayout;
Button buttonOne, buttonTwo, buttonThree, buttonFour, buttonFive;
Button buttonSix, buttonSeven, buttonEight, buttonNine;
ImageView scalingBackground;
int screenWidth, screenHeight, finalSquare;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainLayout = (RelativeLayout) findViewById(R.id.main_layout);
layoutTwo = (RelativeLayout) findViewById(R.id.layout_two);
scalingBackground = (ImageView) findViewById(R.id.image_view);
initializeButtons();
squareBackground();
}
private void squareBackground() {
screenWidth = mainLayout.getLayoutParams().width;
scalingBackground.getLayoutParams().height = screenWidth;
scalingBackground.getLayoutParams().width = screenWidth;
layoutTwo.getLayoutParams().height = screenWidth;
layoutTwo.getLayoutParams().width = screenWidth;
}
Not quite sure whats going on here, I'd appreciate a kick in the right direction. Thanks
You can use a custom imageview in which height and width are same.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:id="#+id/layout_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
>
<com.packagename.SquareImageView
android:id="#+id/image_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="#drawable/bg" />
<Button
android:id="#+id/button_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button_one" />
....
</RelativeLayout>
</RelativeLayout>
Create a class for custom imageview.
public class SquareImageView extends ImageView {
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
}
}
I have created a custom layout for the Action Bar : which I add with this code on my Activity :
LayoutInflater inflater = (LayoutInflater)getSystemService (Context.LAYOUT_INFLATER_SERVICE);
View actionBarView = inflater.inflate (R.layout.main_actionbar, null);
getSupportActionBar ().setCustomView (actionBarView);
and the main_actionbar.xml layout :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:style="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white" >
<RelativeLayout
android:id="#+id/leftIcons"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toLeftOf="#+id/empty"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:background="#drawable/uiclickable_gray_states"
android:layout_alignParentLeft="true" >
<ImageView
android:id="#+id/back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:layout_marginRight="5dp"
android:src="#drawable/icon_back" />
<!-- The problem is here -->
<ImageView
android:id="#+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toRightOf="#+id/back"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:src="#drawable/bg"
android:scaleType="fitXY"
android:adjustViewBounds="true" />
</RelativeLayout>
<View
android:id="#+id/empty"
android:layout_width="100dp"
android:layout_height="match_parent"
android:background="#color/black_transparent"
android:layout_alignParentRight="true" />
</RelativeLayout>
My problem is that I would like the #+id/thumbnail to have it's height as match_parent and have it's width equals the height. means : height == match_parent AND width == height, so I can have a square Image.
it appears that this cannot be done by xml, so I created (with the help of some tutorials on the net) a subclass of ImageView and did this but without any positive results :
#Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
//int width = measureWidth (widthMeasureSpec);
int height = measureHeight (heightMeasureSpec);
setMeasuredDimension (height, height);
}
private int measureHeight (int measureSpecHeight) {
int result;
int specMode = MeasureSpec.getMode (measureSpecHeight);
int specSize = MeasureSpec.getSize (measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = canvasSize;
}
return (result + 2);
}
Am I doing something wrong there ? Thank you.
I have a FrameLayout, containing various overlayed ImageViews:
<FrameLayout
android:id="#+id/australia_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/australia"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/map_australia"
/>
<ImageView
android:id="#+id/nsw"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/map_nsw"
android:visibility="invisible"
/>
<ImageView
android:id="#+id/victoria"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/map_victoria"
android:visibility="invisible"
/>
...etc...
</FrameLayout>
In my code I try and render my FrameLayout:
final Dialog dialog = new Dialog((Context) parent);
dialog.setContentView(R.layout.dialog_region);
FrameLayout fl = (FrameLayout) dialog.findViewById(R.id.australia_frame);
final int height = fl.getHeight();
Validate.isTrue(height > 0);
My code crashes with:
java.lang.IllegalArgumentException: The validated expression is false
at org.apache.commons.lang3.Validate.isTrue(Validate.java:180)
The line that's crashing is Validate.isTrue(height > 0);.
Why does my FrameLayout not have a height? Is there a way to get the exact px height and width that my FrameLayout is rendering at?
This may help you
FrameLayout target = (FrameLayout) dialog.findViewById(R.id.australia_frame);
target.post(new Runnable() {
#Override
public void run() {
int width = target.getWidth();
int height = width/2;
/*your code with width and height*/
}
});
}
I have to define 5 layouts on the screen and place them like a 3x3 grid. Layouts is empty.
At some moment I want programmatically to add some view on one layout and that view mustn't grows over allocated size of layout. In other words I want to have layout in which to put any view and it will be guaranty that it won't grows over that layout. Important note: I don't have rights to change manually size of added view, I only can to control its maximum size.
I have right now such layout:
<RelativeLayout
android:id="#+id/pluginsLayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/mainButtons"
android:layout_below="#+id/paramsLayout">
<RelativeLayout
android:id="#+id/capturingPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="fill_horizontal|left"
android:layout_above="#+id/processingPluginLayout">
</RelativeLayout>
<RelativeLayout
android:id="#+id/processingPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="fill_horizontal|left"
android:layout_above="#+id/filterPluginLayout">
</RelativeLayout>
<RelativeLayout
android:id="#+id/filterPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="fill_horizontal|left|bottom"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true">
</RelativeLayout>
<RelativeLayout
android:id="#+id/exportPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="fill_horizontal|right"
android:layout_above="#+id/viewfinderPluginLayout">
</RelativeLayout>
<RelativeLayout
android:id="#+id/viewfinderPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="fill_horizontal|bottom|right"
android:layout_toLeftOf="#+id/filterPluginLayout"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true">
</RelativeLayout>
</RelativeLayout>
And I added new view in code:
public void addVFPluginView(View view)
{
((RelativeLayout)MainScreen.thiz.findViewById(R.id.viewfinderPluginLayout)).addView(view);
}
I expect to got like this behaviour:
But I got only this, view fill entire parent layout:
Note: I use API8 (don't have GridLayout)
u can use grid layout in API8.
I've managed to solve this issue.
The main idea was to control view's sizes by myself programmatically.
I calculate appropriate proportion for each zone and when somebody add a new view to some of this layout I check suitability of the size of this view to the allocated size of layout. If size is not suitable I modify LayoutParams for this View.
Here is the xml of empty layouts:
<RelativeLayout
android:id="#+id/pluginsLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/mainButtons"
android:layout_below="#+id/paramsLayout">
<LinearLayout
android:id="#+id/capturePluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true">
</LinearLayout>
<LinearLayout
android:id="#+id/processingPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true">
</LinearLayout>
<LinearLayout
android:id="#+id/filterPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true">
</LinearLayout>
<LinearLayout
android:id="#+id/exportPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true">
</LinearLayout>
<RelativeLayout
android:id="#+id/viewfinderPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true">
</RelativeLayout>
</RelativeLayout>
And like that I manage the size of adding views:
public void addVFPluginView(View view)
{
//Get maximum width and height for such plugins
int layoutHeight = this.getViewfinderLayoutHeight();
int layoutWidth = this.getViewfinderLayoutWidth();
//Calculate appropriate size of added plugin's view
android.widget.RelativeLayout.LayoutParams viewLayoutParams = (android.widget.RelativeLayout.LayoutParams)view.getLayoutParams();
viewLayoutParams = this.getTunedRelativeLayoutParams(view, viewLayoutParams, layoutWidth, layoutHeight);
//Get fixed maximum size for this plugin type
public int getViewfinderLayoutWidth()
{
return ((RelativeLayout)MainScreen.thiz.findViewById(R.id.pluginsLayout)).getWidth()/2;
}
public int getViewfinderLayoutHeight()
{
return (int)(((RelativeLayout)MainScreen.thiz.findViewById(R.id.pluginsLayout)).getHeight()*0.7);
}
((RelativeLayout)MainScreen.thiz.findViewById(R.id.viewfinderPluginLayout)).addView(view, viewLayoutParams);
}
android.widget.RelativeLayout.LayoutParams getTunedRelativeLayoutParams(View view, android.widget.RelativeLayout.LayoutParams currParams, int goodWidth, int goodHeight)
{
int viewHeight, viewWidth;
if(currParams != null)
{
viewHeight = currParams.height;
viewWidth = currParams.width;
if(viewHeight > goodHeight || viewHeight <= 0)
viewHeight = goodHeight;
if(viewWidth > goodWidth || viewWidth <= 0)
viewWidth = goodWidth;
currParams.width = viewWidth;
currParams.height = viewHeight;
view.setLayoutParams(currParams);
}
else
{
currParams = new android.widget.RelativeLayout.LayoutParams(goodWidth, goodHeight);
view.setLayoutParams(currParams);
}
return currParams;
}
Finally, next issue is for several views with suitable sizes but in sum they're bigger than allocated size. Maybe I'll just straightly count sizes of views and if the sum with the size of next adding view will be more than allocated size I just disallow to add this view.