Difficulty getting the height of a custom view on cold start - android

I'm having some difficulty in getting the height of a view. Currently, upon a cold start of the app, getMeasuredHeight() on the view returns 0.
Now, I know of ways to get around this. It's occurring because the view hasn't been laid out yet. Unfortunately, using something like a addOnGlobalLayoutListener won't suffice; I need the height of this view (a toolbar + TabLayout or just a toolbar depending on the user's settings) to set the offset for a SwipeRefreshLayout using setProgressCircleOffset(). Upon a cold start of the app, the SwipeRefreshLayout is shown to be "refreshing". Anytime data is loading or changing, it's shown to be " refreshing". If I don't know the height, then the SwipeRefreshLayout won't show that it's "refreshing". I can't delay the calculation as I need it at the beginning of a cold start; not to mention it may be one of two possible heights.
So my question is this: since we can get the DPI of a device, and I can generally estimate (by trial and error) the height (in dp) of the view (and it's alternate)--is it possible to create a "formula" or something that will adapt the offset based on screen size? I know I'd need to convert the dp to px, but beyond that, I'm unsure of how to go about this.
For example, I know the height of this view is 334px on my Nexus 6 (set to 513dpi); but it's definitely less on my stock Pixel C (the offset of 334px is too much on a Pixel C).

So I ended up solving this thanks to AMAN77.
I got the height of the device display (total height in pixels) then multiplied that by a percentage (that I got by trial and error) for the offset.
Here is what I did:
int screenHeight = getContext().getResources().getDisplayMetrics().heightPixels;
int headerOffset = Math.round((float) (screenHeight * 0.13));
//if the user has the "toolbar" setting enabled, we need a different offset
if (SettingValues.single) {
headerOffset = Math.round((float) (screenHeight * 0.07));
}
mSwipeRefreshLayout.setProgressViewOffset(false,
headerOffset - Reddit.pxToDp(42, getContext()),
headerOffset + Reddit.pxToDp(42, getContext()));
Worked like a charm!

Related

how to get fullscreeen height on S9 and similar?

My current android code to retrieve the screen height in pixels is this:
Resources.getSystem().getDisplayMetrics().heightPixels
However when the app is running in full screen mode on Samsung S9 (and probably on similar devices) the returned height is the same as it is when the app is not running fullscreen, i.e. it is calculated without the buttons menu bar that is gone when we're in fullscreen.
Any ideas on a better way to retrieve the height or possibly to be aware of the fact that the app is running full screen?
You can use
val size = Point()
windowManager.defaultDisplay.getRealSize(size)
size.y // will be your needed height
or in Java
Point size = new Point()
getWindowManager().getDefaultDisplay().getRealSize(size)
size.y // this one will be your height
Hope it's what you need.

Comparing MotionEvent.getX() with screen width in Android

I've created an OnTouchListener for motion events in an activity, and I want to find where they happen relative to the screen.
I can use event.getRawX() to find the x co-ordinate, and similarly windowManager.getDefaultDisplay().getMetrics(new DisplayMetrics()) or ...getSize(new Point()) to get the display dimensions.
The problem I'm having is that the display dimensions are consistently reporting the width as 1080, but the motionevents I receive return numbers greater than 1800 for getRawX().
Using the deprecated display.getWidth() returns something close, around 1700 - but even this is lower than what's reported at the right edge of the screen.
I assume motion events use a different co-ordinate system to the display metrics - but how can I convert between the two?
Cheers
Nic
So, I have an answer. This is down to my own stupidity.
What I forgot to mention is that I am viewing the screen in landscape mode. Using v.getWidth(), rather than the display dimension, returns 1920, which makes much more sense.
So obviously (with hindsight) the view width takes into account the orientation, which the display width doesn't - so I've been reading the portrait width (1080) rather than the landscape width/portrait height (1920).
Goodness knows what display.getWidth() was returning...
Thanks to anyone who read and thought about this, and Mihriban for reformatting it.

Effectively measure the available screen

I need to find a way to actually get the dimensions of the screen of my device. I've been trying for long time now and there I cannot find a way to find the height and width in pixel of the drawable screen.
Here is the code I'm using right now:
SCREEN_HEIGHT = metrics.heightPixels - unusable_height;
Where unusable_height is found by:
//Calculate action Bar Height
if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)){
unusable_height = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
}
//Calculate the navigation bar height
int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
unusable_height = unusable_height + getResources().getDimensionPixelSize(resourceId);
}
This works pefectly in my tablet however in my phone the resulting screen height is too large as stuff gets drawn off the screen. (And I calculate all my sizes according to the screen height). This is in landscape mode.
Any help? How can I know the total number of pixels from the end of the action bar to where I can't draw anymore.?
In my phone the navigation bar doesn't rotate so it stays where the bottom would be in portrait mode. So the bottom is the end of the screen. However in my tablet the navigation bar rotates and is put at the bottom of the screen.
I found a way to bypass the problem. However it is not neat. I'm posting it here in case anyone else needs it. It is possible to get the width and height by getting those variables form a layout or view whose LayoutParams were set both to MATCHPARENT. Of course this view needs to be that is set to setContentsView, so it should be like the master layout. However this will thrown non-zero values only when the view is already drawn, which means that you can't get its values in methods like on onCreate or onResume.
On the plus side, it should allways work and it is very simple.

How to make my android component as size dependent for various display screen sizes?

I am making an android component which allows user to pick date from it. It can be helpful for developer who wants user to select date in his app. In my basic view, I have TextView where date from pop up will be populated into it and I have a button beside TextView. When a User clicks on the button, my component gets popped out and displays Dates. The component gets pops out in a Popup window and shows dates as month view and user also can switch from next-previous months, next-previous years just like we do in Calendar. Check the Image.
http://s15.postimage.org/ujw8py60b/stackoverflow.jpg (Sorry, I couldn't upload an image here because I am not allowed as I am new User here)
Each date is a TextView with the width of 35 and height as 30 set by me. DaysDisplayBar is also of some size set by me. So this component's whole width is 245 and height is around 200. Which is for mobile screen size.
I want to make this component as size dependent for various screen display sizes. For e.g. If it is being viewed on Tablet or Pad, it should be bigger in size than what its size on mobile phone screen. That is, For various displays its size should be changed to some value like max 1/3 of display size or like that something.
What can be the solution for this? According to me, some mathematics is needed here, some formula, equations etc. how about Parabola? Please help, I am dumb in maths totally. Thanks! :D
"Each date is a TextView with the width of 35 and height as 30 set by me. DaysDisplayBar is also of some size set by me. So this component's whole width is 245 and height is around 200. Which is for mobile screen size."
^^ is the problem. Sizes should be defined relative to the layout, not absolute. For example, the calendar has 7 columns (one for each day). Instead of making each one 35px, make each 1/7th of the screen.
SO:
I am assuming a DaysDisplayBar is a row containing 7 TextViews (one for each day). If that is true, why not call it a Week? Either way, The trick is in layout_wieght. Make all elements fill_parent, and all with the same weight of 1. This will evenly distrubate all elements in the parent. In your case, the parent is a DaysDisplayBar.
SO:
set DaysDisplayBar attribute `layout_width="fill_parent"
For each TextViewset attribute layout_width="fill_parent" ANDlayout_weight="1"`
hope that helps!
First of all, make sure you use density pixels (dip) instead of pixels.
Second, you can get the screen width and height, and from there, calculate your component size.
You can get the screen dimensions using the Display class getSize() method:
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point screenSize = new Point();
display.getSize(screenSize);
int screenWith = screenSize.x;
Or you can get the parent view dimensions:
MarginLayoutParams params = (MarginLayoutParams)parentView.getLayoutParams();
int padding = parentView.getPaddingLeft() + parentView.getPaddingRight();
int margin = params.leftMargin + params.rightMargin;
int measuredWidth = parentView.getMeasuredWidth() - padding - margin;
That way you know how much space you have inside the parent view element for your component.
Remember to convert any hard coded value to dip, you can do it this way:
public static int getDensitySize(float size) {
float density = getResources().getDisplayMetrics().density;
return (int)(density * size);
}
You do all of this from your onMeasure method to set your view size, and later on the onDraw you'll use this measure to draw your component.

Getting my app to show all or none of the image in a scroll view

I currently have 10 images in a horizontal line in a separate table view that is part of a scroll view. Now, if I scroll to the right, and release, the app will stop wherever it is (sometimes when it's halfway past an image, so only half of that image is left displayed).
Ideally, what it should do is 'bounce back' when I've released my finger to show all of the image it has half of, or none of it. I guess the easiest way to do this would be to decide what to do based upon how far across it has scrolled. For example, if I have an image of 201dp width and I stopped scrolling when 150dp of that image was still visible, it should bounce back to show all of the image. Alternatively, if only 20dp of the image was visible, the bounce back should revert to not showing the image and reverting to another one that would be on the screen (just like the BBC app does).
One other way of explaining it is to think of a slot machine. When you spin the reels it will never stop halfway on an item, it will always stop in the correct place to show all of it. This is what I need.
Thank you in advance for anyone who can help me out with this one, I really appreciate it!
if(scrollX % imageWidth < imageWidth / 2){
scrollX -= scrollX % imageWidth;
}else{
scrollX += (scrollX % imageWidth) - imageWidth;
}
This will do the rounding, where scrollX is how far you have scrolled on the x-axis and imageWidth is the width of all your images.

Categories

Resources