I am trying to occupy as much space as available on notched android devices. In Flutter development, there is widget called SafeArea which automatically adjusts your view depending on whether the device has a notch or not. Even in iOS development whenever we add constraints using storyboard, we can add it according to SafeArea.
But I couldn't find anything similar to it in Native Android development.
In my styles.xml for v28 I have added something as follows
<style name="TPAFTheme" parent="#style/Theme.AppCompat.Light.NoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
But is it possible to detect whether device has Notch or not in layout file itself and adjust the layout according.
I am using Constraintlayout in my App. As my app has image at the top it gets cropped if the device has notch at the top.
Any help would be appreciated.
I finally found the answer. Just use android:fitsSystemWindows="true" in your ConstraintLayout or any other top level Layout which you're using
I think the right option is to use CoordinatorLayout as a parent for your ConstraintLayout. CoordinatorLayout does lots of things and handling the system area is one of them (which I'd say isn't obvious...). It internally sets OnApplyWindowInsetsListener which is called by the system with information about sizes of system elements. CoordinatorLayout handles this calls and sets the right padding for its children. So, in Android it's more complicated than in iOS, you'll have to get used to it...
I'd recommend this video: https://www.youtube.com/watch?v=_mGDMVRO3iE
Related
According to the documentation
A Button which supports compatible features on older versions of the
platform, including:
Allows dynamic tint of its background via the background tint methods
in ViewCompat. Allows setting of the background tint using
R.attr.backgroundTint and R.attr.backgroundTintMode. This will
automatically be used when you use Button in your layouts and the
top-level activity / dialog is provided by appcompat. You should only
need to manually use this class when writing custom views.
Now, this makes me assume that the following two buttons would look exactly the same on high level devices.
<androidx.appcompat.widget.AppCompatButton
android:text="AppCompatButton"
android:id="#+id/appcompatbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:layout_below="#id/appcompatbutton"
android:id="#+id/button"
android:layout_width="wrap_content"
android:text="Button"
android:layout_height="wrap_content" />
However, here is how it actually looks:
I ran this on the following emulator:
Galaxy Nexus, API:28 (720 x 1280 xhdpi)
And when I apply buttonStyle in my appTheme like this:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="buttonStyle">#style/Widget.MaterialComponents.Button</item>
</style>
It changes the AppCompatButton but not the normal button like this:
(Note the slight difference in the rounded edges)
I also tried to create a custom button that both inherited from android.widget.Button and also androidx.appcompat.widget.AppCompatButton, both of these buttons show the same behaviour as using AppCompatButton in xml does. So it feels like the only outlier is Button in XML.
Question 1:
This all seems incredibly confusing according to me. Can someone clarify this as either a bug or feature?
EDIT 1
Doing debugging I found that the Button actually gets transformed into a MaterialButton, see the following:
Question 2:
Why is this transformation happening?
EDIT 2
Question 2 answer:
The transformation of Button to MaterialButton is due to the parent theme I was using.
Question 3:
How do you implement a custom button which works just like Button in xml would?
As a side note and personal opinion, also a slight repetition, this system is not only confusing but its hard to get it right and foolproof for future changes. In addition to this, the documentation is very poor. I would appreciate if an answer to this would be included as well, or at least a discussion regarding it, how to deal with it for example.
Short answers.
This all seems incredibly confusing according to me. Can someone clarify this as either a bug or feature?
They use different styles.
Why is this transformation happening?
There is an auto-inflation enabled which will replace <Button with <com.google.android.material.button.MaterialButton at runtime.
How do you implement a custom button which works just like Button in xml would?
You can customize the attributes in xml or the theme attributes.
Long answers.
They use different styles.
The default style of MaterialButton is Widget.MaterialComponents.Button.
This style inherits from Widget.AppCompat.Button but changes some attributes.
Here you can find the differences.
The main difference is here:
<item name="shapeAppearance">?attr/shapeAppearanceSmallComponent</item>
You can read more about shaping in the official doc.
If you navigate through the style you will find:
<style name="ShapeAppearance.MaterialComponents.SmallComponent">
<item name="cornerSize">#dimen/mtrl_shape_corner_size_small_component</item>
</style>
where mtrl_shape_corner_size_small_component = 4dp.
It explains the slight difference in the rounded edges.
Also you are using
<item name="buttonStyle">#style/Widget.MaterialComponents.Button</item>.
It doesn't work for the MaterialButton. You have to use:
<item name="materialButtonStyle">#style/Widget.MaterialComponents.Button</item>
The auto-inflation is here.
The MaterialComponentsViewInflater replaces some framework widgets with Material Components ones at inflation time, provided a Material Components theme is in use.
Something similar happens also with AppCompat (you can check that MaterialComponentsViewInflater extends AppCompatViewInflater).
It means that, the <Button is replaced <com.google.android.material.button.MaterialButton at runtime, if you are using a Material Theme.
There are different options. One of these is to define a custom style for buttons.
<style name="AppTheme" parent="Theme.MaterialComponents.Light">
...
<item name="materialButtonStyle">#style/MyButtonStyle</item>
</style>
<style name="MyButtonStyle" parent="Widget.MaterialComponents.Button">
<item name="cornerRadius">xxx</item>
</style>
or
<style name="MyButtonStyle" parent="Widget.MaterialComponents.Button">
<item name="shapeAppearanceOverlay">#style/SShapeAppearanceOverlay.MyApp.Button.Rounded</item>
</style>
<style name="ShapeAppearanceOverlay.MyApp.Button.Rounded" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">xxdp</item>
</style>
I changed the <Button> to <ImageButton>
Quick and short way.
Don't forget to check & change references in java/kotlin files. Compiler will alert you any way.
I have noticed that on android versions 6.0+,when someone starting app after login screen and submiting info,black screen appear and you have to wait 3-15 sec depending on devices.
I heard that it could be for heavy loadings,but this app is nothing special it just load listview with few images after login (i had 3 images while tested) so im not sure is it really that heavy plus it only happen on newer versions of android so im not sure what to do.
I can provide whole code or some snippet.
EDIT: I tried with various image sizes (full loaded with big images,and only 1 small image) and it have no effect at all.
Anyone???
Inside your manifest file .
In your Activity tag add this theme.
android:theme="#android:style/Theme.Translucent"
And then you need to extend your respective activity from Activity class.
It will work for sure
For those who face this error in future
<style name="FullscreenTheme" parent="MainTheme">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowIsTranslucent">true</item>
</style>
My Samsung Galaxy s7 just updated to Android Nougat 7.0 and I noticed some of the buttons are displayed differently. I happen to have another Galaxy s7 around which hasn't gone through the update yet (Marshmallow 6.0.1). I can see the difference in sizes very clearly:
Marshmallow:
Nougat:
The layout_height of that SHARE button is hard set to 44dp. Using Layout Inspector in Android Studio I can read that it resolves to 176px for Marshmallow and 132px for Nougat (same values for mMeasuredHeight). You can also see that the other part of the layout on the left remained the same (ignore the little thumb up icon).
Another example:
Marshmallow:
Nougat:
I'm using following styling for the buttons:
<style name="AppTheme.Button" parent="Widget.AppCompat.Button">
<item name="android:textSize">14sp</item>
<item name="android:textColor">#color/colorPrimaryDark</item>
<item name="android:backgroundTint" tools:targetApi="lollipop">#color/colorTextBrightPrimary</item>
<item name="backgroundTint" >#FFFFFF</item>
<item name="colorButtonNormal">#color/colorTextBrightPrimary</item>
</style>
<style name="AppTheme.Button.Accent" parent="AppTheme.Button">
<item name="android:textColor">#color/colorTextBrightPrimary</item>
<item name="android:backgroundTint" tools:targetApi="lollipop">#color/colorAccent</item>
<item name="backgroundTint" >#color/colorAccent</item>
<item name="colorButtonNormal">#color/colorAccent</item>
</style>
While the SHARE button is a custom view, extending AppCompatButton, the Google and Facebook auth buttons are just AppCompatButtons. In either way, they all looked different just before the update and nothing else was changed in code, nor on the device (text size and zoom are the same).
Any idea what's going on? How to ensure these layouts stay the same on various devices/OS'?
A drawable can have its own padding. In the case of a nine-patch PNG file, that's simply having transparent pixels outside of the actual non-transparent/resizing portion of the image. In the case of ShapeDrawable, you can directly declare padding in the XML. And so on. This may or may not show up as "padding" in tools like the Layout Inspector, as they focus on padding declared on widgets.
Since the previous background you were using had the problem, and the replacement background does not, my guess is that this sort of implicit padding is the problem.
You have two approaches for trying to deal with this:
The risky-but-simple approach is to try using negative padding on the button itself, in a res/values-v24/ variant of your style resources (or, optionally, use a consistent dimension resource in the style and vary the dimension values based on -v25 or not). You would have to tinker a bit to try to get values that "undo" the change. I call this "risky" as I haven't the foggiest notion how well Android respects negative padding.
The aggravating approach is to try to find the actual button background that you were using before, and see what changed about it. The drawables would be declared either in appcompat-v7's themes or the platform's themes, and the actual drawables themselves would then be defined either in appcompat-v7 or in the platform.
I am using the ActionBar Compatibility, everything is OK, except the fact that by default, the buttons (actions) have some padding around.
How can I alter that padding for specific buttons, remove it, and in some cases adjust.
I managed to resolve this issue by creating a custom layout and attaching it to the ActionBar, by configuring the styles:
<style name="ActionBar" parent="android:style/Widget.Holo.Light.ActionBar">
<item name="android:displayOptions">showHome|useLogo|showCustom</item>
<item name="android:customNavigationLayout">#layout/actionbar_custom_title</item>
</style>
Now there appeared another problem: Please see this thread if you can help me: Android - Remove "More actions" button from the ActionBar
Currently, I'm using this to show my application background as phone wallpaper.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER,
WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
But for some reason when I start my application by pressing the icon. It just shows the activity screen with the icons on the home screen. I didn't use dialog but it looks like a dialog because layout is just set that way. So I just want to show the wallpaper whenever this activity is running. But it only shows the wallpaper only after the next event occurs such as switching to different activity. I already put that code on onCreate() and whenever I do setContentView()..... Is there way to do such thing or there is just no way?
For users of AppCompat, just use the following in your styles.xml, no need for code:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat">
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">#null</item>
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowTranslucentStatus">true</item>
</style>
After long search and trial and error. I've found the solution to what I wanted. It was just creating separate themes.xml file and just tweak the Theme.Dialog which is already defined in default android themes.xml. All I did was change the Animation part. Originally in android themes.xml the line looks like this.
<item name="android:windowAnimationStyle">#android:style/Animation.Dialog</item>
but since modifying in android themes.xml doesn't take the effect. I just created my own themes.xml as I said above and just set parent as android:Theme.Dialog. And added a line like this.
<item name="android:windowAnimationStyle">#android:style/Animation</item>
Thanks for the help and I hope this solution helps others.
Use following code -
rl = (RelativeLayout)findViewById(R.id.someid);
//relative layout is my root node in main.xml (yours may be linearlayout)
WallpaperManager wm = WallpaperManager.getInstance(this);
Drawable d = wm.peekDrawable();
rl.setBackgroundDrawable(d);// You can also use rl.setBackgroundDrawable(getWallpaper);