control dimensions of custom alert dialog in different screen orientations - android

I want to set dimensions for my custom alert dialog, based on screen orientation. My intention is to swap height and width values to keep the box look like being the same size, yet handled various screen sizes of various devices, thanks to Android fragmentation it seems difficult to achieve the same effect on all devices. Android's auto-resizing seems weird to me.
Portrait:
alertDialog.width=screen.width*0.8
alertDialog.height=screen.height=0.5
Landscape:
alertDialog.width=screen.width*0.5;
alertDialog.height=screen.height*0.8
Please note that the Custom Alert Dialog must use the same code and support Android versions from JellyBean (at least 4.2) to Nougat (7).
i am using android.support.v7.AlertDialog (the latest available thing)
i assume android.app.Dialog should be avoided now (being old)
Also, i need a black border and white background for the same. i am unable to achieve same effect on all devices, (i need transparency for rounded corners)
i have used android:windowMinWidthMajor and android:windowMinWidthMinor but they affect both layouts (portrait and landscape) and seem to be ignored if content does not fit within the specified constraints.
I wish there was android:windowMaxWidthMinor & android:windowMaxWidthMajor

This is something that I've used for resizing specific views on a page:
myView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
item.height = myView.getHeight();
});
Applying it to what you want to do:
myView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
LayoutParams params = (get the layout params according to the layout);
params.width = myView.getWidth() * 0.5;
params.height = myView.getHeight() * 0.8;
myView.setLayoutParams(params);
});
You have to use the listener because the object will be added to the view tree, will be measured and prepared for display, but won't yet be displayed, so you can change its dimensions before it is visible.

Update:
I could achieve it by setting android:layout_centerInParent="true" for my Layout. and layout values for each component in the style to
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_gravity="center"
to achieve the center alignment.
XML Code available at https://github.com/computingfreak/CFTest/blob/master/app/src/main/res/layout/alert_popup.xml
Java Code available at
https://github.com/computingfreak/CFTest/blob/master/app/src/main/java/net/cf/sms/cftest/MainActivity.java
I wonder this line of code is redundant
view.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
and thus left it to Android System to decide dimensions and resizing based on content. It works for my case, but will fail in case of long text, maybe some kind of Scroll Layout will help. Cheers!

Related

How to make Percent dynamic in PercentRelativeLayout?

I am using PercentRelativeLayout from Design Support Library and i want to set different Percentage for 7 inch and 10 inch tablet.
For example if i have ImageView like below.
<ImageView
android:id="#+id/contactDoc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_widthPercent="70%"
app:layout_heightPercent="70%"
android:layout_centerHorizontal="true"
android:clickable="true"
android:src="#drawable/dashboard_contactdoctor" />
now if i want to set 70% for 7 inch tablet and 60% for 10inch tablet without making different layout folder like sw720dp . Can i do it?
Help is appreciated.
Those percentages are fraction resources. You should be able to set up res/values/fractions.xml and res/values-sw720dp/fractions.xml, where you define the values for the fractions. Then, use #fraction/whatever_you_called_it in the layout.
You can use different layouts for different screen sizes. You can read more about it in the documentation: https://developer.android.com/training/multiscreen/screensizes.html
A possibility wihtout providing multiple layouts would be to place the ImageView inside a LinearLayout with a android:weightSum of 10 and then set the weight of the ImageView programmatically:
LinearLayout.LayoutParams layoutParams = yourView.getLayoutParams();
layoutParams.weight = WHATEVER;
yourView.setLayoutParams(layoutParams);
Try using constraint layout, it is available on android studio 2.2 and after .
By using this, you can add both vertical and horizontal guideline according to screen percentage and then you set the height and width of your imageview relative to those guideline
First of all, you are going to need to detect 7" or 10" tablet. I assume that you already know how to do it based on your question. If not, check out this great answer.
After you know what device are you dealing with, use the following code to put inside an if condition (or somewhere else) to define the percentage of your view in code:
View view = findViewById(R.id.yourView);
PercentLayoutHelper.PercentLayoutParams params =
(PercentRelativeLayout.LayoutParams) view.getLayoutParams();
PercentLayoutHelper.PercentLayoutInfo info = params.getPercentLayoutInfo();
info.heightPercent = 0.60f;
view.requestLayout();
Based on another great answer.

Android default button designers fixed size

This question might be trivial to some of you.
I am facing a dumb issue working with designers and developers.
According to the designers the android button from material design has a particular style, default button style (top button in the image).
Designer defines a fix height and width 50dp for instance. So they expect to have a button of those dimensions.
But developers when using a default android button, the default button contains margins.
So we use a custom drawable background, in this case the button has the expected dimensions (button a the bottom). But the style is not exactly the same (very few differences, but still). We could try to imitate the default style, but I am not sure it is worth.
So how do you do when working with designers that just use a default button from the material android patterns and expect to have the exact size?
You consider size with margins? You create a background style? You try to imitate as much as you can the default button? others?
and this is the simple code used
<Button
android:layout_width="50dp"
android:layout_height="50dp"
/>
<Button
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#drawable/my_button_shape"/>
tha parameter margin is deferent then hight and width. margin determines the distance from point A to the button.
to et the height and width you can use in your xml file the following code:
example:
<Button
android:id = "#id/myButton"
android:layout_width = "50dp"
android:layout_hight = "50dp"
android:text = "test"
android:layout_marginTop = "100dp"
/>
the margin top 100dp determines that my button is 100dp from the top of my layout but the width and height determines the button size
The problem is 9-patch for the default button already includes a margin, so visually the button looks smaller than expected. Possible solutions include negative margins or duplicating the default 9-patch and removing the margin, but each option has its own drawbacks.
As #egonzal says, it would be interesting to know other developers solutions when facing the problem.

Avoid animation on orientation change to prevent ugly view stretching

Introduction
My app should show a button that fills up the entire screen, but stays quadratic. I have accomplished that by referencing orientation-dependend dimen-values:
activity_main.xml
<ImageButton
android:id="#+id/fartbutton"
android:layout_width="#dimen/fartbuttonWidth"
android:layout_height="#dimen/fartbuttonHeight"
android:layout_gravity="center"
android:src="#drawable/sel_fart_button"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:background="#android:color/transparent"
android:clickable="false"/>
dimens-land/dimens.xml
<resources>
<dimen name="fartbuttonWidth">#dimen/wrap_content</dimen>
<dimen name="fartbuttonHeight">#dimen/match_parent</dimen>
</resources>
dimens-port/dimens.xml
<resources>
<dimen name="fartbuttonWidth">#dimen/match_parent</dimen>
<dimen name="fartbuttonHeight">#dimen/wrap_content</dimen>
</resources>
This was to ensure, that the ImageButton couldn't be pressed by touching the top of the screen, which would be far away from the image.
I since have implemented a check to ensure, that the button only reacts to presses on an opaque part of the image, ignoring touch on transparent areas. There this might not be as necessary anymore.
I also have programmed a widget on which I think I'm not able to change the layout programmatically. That's why solutions to the following problem that work entirely within the XML-files are prefered.
The problem
I know that when I change the orientation of my device, the activity gets completely destroyed and recreated. In that process, the OS transitions between the two states with a nice (and wanted) rotation. However, it also stretches and fades the two buttons in an ugly way, as shown in the image.
I assume that it tries to respect the match_parent attribute of the old button and therefore stretches the image to match the full new width.
I already searched for how to disable activity transitions and tried to find an existing solution to my problem. Sadly, since most people would like to add custom animation to orientation changes or disable the rotation animation completely, my searches for this problem haven't been successfull.
Is there an easy way to circumvent this ugly stretching? Would a shared element activity transition work? What solutions come to you mind? :)
Edits
First edit
Seems like setting all dimensions to wrap_content (even that of the FrameLayout) and fixing the button's dimension to 200dp don't work. Now I assume that the OS is simply taking a screenshot and stretching it to the new landscape proportions or vice versa.
Is there a way to disable this behavior? The new button is fully opaque and rotates just fine. It probably would be enough to disable the fading animation.
Second edit
I now noticed this behaviour in all the apps on my phone. I could not find a way to tell Android to just not do it... :(
You can create a square FrameLayout by subclassing FrameLayout and overriding onMeasure:
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int size = width > height ? height : width;
setMeasuredDimension(size, size);
}
Then wrap your button in this FrameLayout in your layout.
As Rahil2952 pointed out referring to this answer, there seems to be no solution. It is a "feature" Android provides, over which the programmer does not have easy control.

Programmatically resize of view depends on android version?

I am facing a weird behavior regarding the subject.
I have a very simple layout containing only an empty RelativeLayout.
Once I have input form the user this relative layout is filled with square tiles to achieve a mosaic-like effect. Each tile is made by a FrameLayout containing two images (only one is drawn at any given time). It is not possible for me to put the tiles in the XML layout because I do not know in advance how many of them I will need.
In the onSizeChanged of my relative layout, I force a resize on all the tiles to fit the new size.
The code is something like this:
public void resizeTiles(int w, int h) {
int l1 = w / X; int l2 = h / Y;
int tileS = (l1 <= l2 ? l1 : l2);
android.view.ViewGroup.LayoutParams lp;
for (Tile t : myTiles) {
lp = t.getLayoutParams();
lp.width = tileS;
lp.height = tileS;
}
}
In my manifest file I have the following:
<uses-sdk
android:minSdkVersion="4"
android:targetSdkVersion="4"
/>
Thus, target system is 1.6.
So far so good, this is working like a charm ... but only on 2.2.
The same binary placed on emulator 2.1-update1 or previous is giving me back an empty layout (I also tried a couple of physical devices, same result).
Debugging, I tracked down the problem is in the resize; commenting out width and height assignments I see the tiles but with distorted proportions.
Any suggestion on how to make this working ?
Thanks in advance.
onSizeChanged() is called late in the layout process, once the final size has been determined. There may already have been some layout passes that have happened down through the hierarchy at that point.
Basic answer is: layout params are for telling the view's parent its layout params prior to is performing a layout. If they change, the layout must be invalidated to perform a new complete layout with the new params. You should never change these in the middle of a layout.
The best thing to do is just write your own layout manager. (If you are doing layout of tiles, RelativeLayout does a ton more stuff that you don't need, making it a lot less efficient than necessary.) It is actually not very hard to write a simple layout manager.
You can use the simple layout managers in the framework as a guide:
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/AbsoluteLayout.java
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/FrameLayout.java
(Note that even these are a lot more complicated than you probably need, since they are intended to be general purpose for the layouts they are implementing. We really should have an API demo of a custom layout that is truly simple.)

Unable to programmatically change width of horizontal progressbar

I would like change the width of a Horizontal Progressbar programmatically (initial size is set in XML using RelativeLayout...but I would like to dynamically change it based on certain values).
I have tried setMinimumWidth(50) in my code, but that did not make a difference. I have also tried setting 'android:layout_width="wrap_content", but that did not work either.
Here is my XML:
<ProgressBar android:id="#+id/progress_horizontal"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="100dip"
android:layout_height="wrap_content"
/>
Thanks in advance for any assistance!
What layout is your ProgressBar in? This makes a difference as to how the layout_width and height are interpreted.
However, I think you are seeing a conflict between the View's width, and the layout_width. Each time the view is rendered, its preferred size is determined based on the minWidth, width, etc. set on it. The layout that the view sits in can then update the actual size to render based on the layout_width information. See How Android Draws Views and View size documentation for more info on the two phase process.
In your case, you have the layout_width set to 100, and the minimum width set to 50, so I would think it would always show 100.
Try setting the layout_width to wrap_content, and then updated the preferred width for the ProgressBar.
I would imagine the setmindwidth would be met when you give it an initial value of 100. the system would receognize it exceeds 50 and then continue to do as the rest of what it's told. try making the min width 150, set the xml for an initial value of 75 and in your onCreate fire off a Log.d("progbar", String.valueOf(myprogress.width));
disclaimer - written when in front of work computer without development environment for reference.

Categories

Resources