Scaling a VectorDrawable on API 19 - java

I'm writing an Android app with minSdkVersion = 15 (testing on 19). I would like to have an overlay with a small phone picture in the middle. I added the drawable (xml) resource ic_smartphone_black_24dp from the standard Android's pictures and created an ImageView for the overlay like this:
<ImageView
android:id="#+id/overlay"
android:layout_width="0dp"
android:layout_height="0dp"
android:alpha="1."
android:background="#drawable/overlay_full"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
This renders the overlay, but the smartphone picture is stretched to the whole ImageView:
I tried to scale the phone's picture in various ways (reading this, that and many others), but none of it worked. In particular I tried:
adding vectorDrawables.useSupportLibrary = true to gradle.build
adding
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
to the Activity
changing the ImageView to android.support.v7.widget.AppCompatImageView (and setting the background in java code and not in xml)
passing wrap_content instead of 0dp as layout_width/height (and removing the constraints)
setting the size in the overlay_full:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#drawable/overlay_background">
<size
android:width="152dp"
android:height="152dp"/>
</item>
<item android:drawable="#drawable/ic_smartphone_black_24dp"
android:left="30dp"
android:top="30dp"
android:right="30dp"
android:bottom="30dp"
android:gravity="center"
android:scaleType="center"
android:width="30dp"
android:height="30dp">
<size
android:width="30dp"
android:height="30dp"/>
</item>
</layer-list>
The code works as expected in API 28 where I also tested. Any idea how to do this scaling in earlier API versions?

You could try something like this:
<ImageView
android:id="#+id/overlay"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="center"
android:background="#drawable/just_the_background"
app:srcCompat="#drawable/ic_smartphone_black_24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
Also, you don't need to use AppCompat views directly in layouts, just let the library handle this for you (they are replaced automatically at build time). You only need to use them if you're extending them to add custom functionality.

Related

How to implement this bottom navigation bar

Hei I have the new android studio 4.1
I have imported a bottom navigation menu from git hub here this one
Now I have set up dependencies correctly
I did all the things necessary but still, there are no actions in the navigation bar, the colour is not changing. even the menus are not displaying
here is the main activity code
<me.ibrahimsn.lib.SmoothBottomBar
android:id="#+id/bottomBar"
android:layout_width="match_parent"
android:layout_height="70dp"
app:backgroundColor="#color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
this is the menu code
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/home"
android:title="Home"/>
<item android:id="#+id/rank"
android:title="Rank"/>
</menu>
now still the background is white see this: image still not changing
Have you added this line in your layout parent tag:
xmlns:app = "http://schemas.android.com/apk/res-auto"

Android doesn't resize with different screen layouts

I am trying to resize my layouts, based on which device I am using.
I am testing on two differents phones (Samsung Galaxy S8+ and Sony Xperia Z2 (and even two different emulators)).
I've added some code into the Manifest file.
I've created different folders with the right (supposedly) names (layout, layout-small, layout-large, layout-xlarge).
I put my code into the values folder, file "dimens.xml" and call it from my layouts.
But nothing seems to work.
The only time my screens are changing is when I am modifying the corresponding file into the "layout" folder.
I would love any help or advice. Thank you!
I've read many times the documentation on Android Developer and Stack Overflow and I can't seem to find a solution.
Snippet of AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.applicationpro">
<supports-screens android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"
android:resizeable="true" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
Snippet of res/layout-large/my_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/mainLL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg4"
android:orientation="vertical"
tools:context=".activity.LoginActivity">
<ProgressBar
android:id="#+id/loginPG"
android:theme="#style/FragmentsProgressBar"
style="#style/Widget.AppCompat.ProgressBar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:layout_marginTop="100dp"/>
<android.support.design.widget.TextInputLayout
android:id="#+id/loginTIY"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/margin_top_large">
<AutoCompleteTextView
android:id="#+id/loginTV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/prompt_login"
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
dimens.xml
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="standard_55">65dp</dimen>
<dimen name="standard_105">135dp</dimen>
<dimen name="standard_155">155dp</dimen>
<!-- Small Dimensions = "Medium Dimensions * 0.75" For Example: 210*.75 = 157.5-->
<dimen name = "margin_top_small">150dp</dimen>
<!-- Medium Dimensions -->
<dimen name = "margin_top_medium">200dp</dimen>
<!-- Large Dimensions = "Medium Dimensions * 1.5" For Example: 210*1.5 = 315 -->
<dimen name = "margin_top_large">300dp</dimen>
<!-- XLarge Dimensions = "Medium Dimensions * 2" For Example: 210*1.5 = 420 -->
<dimen name = "margin_top_xLarge">400dp</dimen>
</resources>
TL;DR
This is another approach using ConstraintLayout and not a single layout for every screen size
You can support different screen sizes by using ConstraintLayout:
ConstraintLayout allows you to create large and complex layouts with a flat view hierarchy (no nested view groups). It's similar to RelativeLayout in that all views are laid out according to relationships between sibling views and the parent layout, but it's more flexible than RelativeLayout and easier to use with Android Studio's Layout Editor.
You can use those attributes to specify your views size in precents:
app:layout_constraintWidth_percent=".5"
app:layout_constraintHeight_percent=".5"
For example, single button that is equal to 50% of the screen both in height and width:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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">
<Button
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent=".5"
app:layout_constraintHeight_percent=".5"/>
</androidx.constraintlayout.widget.ConstraintLayout>
And it will look something like this:
I can recommend using ConstraintLayout with guidelines and Chains to support different screen sizes (In addition to what I mentioned above - app:layout_constraintWidth_percent and app:layout_constraintHeight_percent).
At first look this may look like a lot of work and some may wonder if this is really worth the effort but here is why I believe ConstraintLayout is the proper way to build your UI:
It's really user-friendly.
ConstraintLayout is very easy and simple to learn.
once you have learned it you will see that you are saving a lot of development time because making your UI is simply fast.
Constraint layout is meant to support different screen sizes so no need to build a layout for every screen size (this also connect to the previous advantage- saving development time).

ImageButton onclick

When I click restart button, it creates blue coloured thing. How to set that blue coloured thing to transparent? Please help me.
Set your image in android:src and set the background as null to remove the visual feedback:
android:background="#null"
Please note that this will remove the visual feedback for button press and is not recommended. Use a selector to set different images depending on the button state for better UX
If you are using "Button", try using "selector" as background(android:background="#drawable/button_selector").
A sample selector -> button_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/button_bg_selected" android:state_selected="true"></item>
<item android:drawable="#drawable/button_bg_pressed" android:state_pressed="true"></item>
<item android:drawable="#drawable/button_bg_normal"></item>
</selector>
use ImageView Instead of ImageButton
<ImageView
android:layout_width="120dp"
android:layout_height="130dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
android:background="?android:selectableItemBackground" android:id="#+id/ibtn_restart" />
and in Java file
ImageView ibtn_restart=(ImageView)findViewById(R.id.ibtn_restart);

API 19 : android.view.InflateException: Binary XML file line #0: Error inflating class SeekBar

I have the following layout file
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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/rootConstraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
tools:context="mtronics.alertme.HomePage">
<TextView
android:id="#+id/tvSpeedSet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="My Limit : 0 Km/h"
android:textAlignment="center"
android:textColor="#color/colorText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/speedView" />
<SeekBar
android:id="#+id/seekBarSpeedSet"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#drawable/corner_fillet_background"
android:max="200"
android:progress="0"
android:thumb="#drawable/icon_seek_thumb"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tvSpeedSet" >
</SeekBar>
<ListView
android:id="#+id/listAlerts"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_weight="1"
android:divider="#color/colorTransparent"
android:dividerHeight="8dp"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/seekBarSpeedSet">
</ListView>
</android.support.constraint.ConstraintLayout>
Drawable files
icon_seek_thumb.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape>
<size
android:height="40dp"
android:width="40dp" />
<solid android:color="#android:color/transparent" />
</shape>
</item>
<item android:drawable="#drawable/ic_seek_thumb"/>
</layer-list>
ic_seek_thumb.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#color/colorText"
android:pathData="...."/>
</vector>
With above layout i am getting following error only for API 19, for higher it is working
NOTE: If i remove android:thumb from seekbar , it works for API 19 also
I am getting following error when i try to execute in API 19
android.view.InflateException: Binary XML file line #0: Error inflating class SeekBar
Support for VectorDrawables was added to the framework in API 21 so they are not supported in API 19 - hence the crash.
The support library provides a backported version VectorDrawableCompat which you are able to use on lower Android versions. Unfortunately if I remember correctly it doesn't hook into the seekbar thumb when inflating from xml.
To get around this you have to create the thumb Drawable in java and set it to your Seekbar manually.
Firstly make sure you have AppCompat in your build.gradle:
api "com.android.support:appcompat-v7:${supportLibVersion}"
Then in the java class where you are using the Seekbar create a new method to set the thumb. The following should be equivalent to your original xml:
private void initThumbDrawable() {
final int size = convertDpToPixel(40);
GradientDrawable square = new GradientDrawable();
square.setShape(GradientDrawable.RECTANGLE);
square.setSize(size, size);
square.setColor(Color.TRANSPARENT);
VectorDrawableCompat thumb = VectorDrawableCompat.create(getResources(), R.drawable. ic_seek_thumb, null);
LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] {square, thumb});
seekBar.setThumb(layerDrawable);
}
private int convertDpToPixel(int dp) {
DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, displayMetrics);
}
It would probably simpler if you included the padding into your vector rather than using a layer list!
Finally be sure to remove the:
android:thumb="#drawable/icon_seek_thumb"
from your layout xml file
Once i had the same problem. I fixed it placing all drawable files under drawable folder. Mine issue was some drawable files were present only in drawable -xxdpi not in drawable folder where lower API level looks for the file..
Replace all your files on drawable folder that may fix your issue.

View appears on Android Emulator but not on physical phone

I have an activity layout consisting of just a ListView. It is supposed to use a list format xml which consists of a custom shape with three TextViews inside. In code I populate the ListView with the desired text, and when I run the app on an AVD, everything works as planned. When I deploy to my Droid Razr, however, the entire screen is blank when I run that activity.
Edit: Added code below
This is my custom shape (drawable):
<stroke
android:width="1dp"
android:color="#ff9f9f9f" />
<padding
android:bottom="20dp"
android:left="20dp"
android:right="20dp"
android:top="20dp" />
<solid
android:color="#color/white" />
<corners
android:bottomLeftRadius="7dp"
android:bottomRightRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />
This is my list format:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:background="#drawable/rounded_edges"
android:orientation="vertical"
android:padding="6dip"
android:theme="#android:style/Theme.Holo.Light" >
<TextView
android:id="#+id/details_list_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceLarge" />
And this is how I use it in code:
ListView listView = (ListView) findViewById(R.id.event_details_listView);
DetailAdapter adapter = new DetailAdapter(this, R.layout.listformat_event_details, details);
listView.setAdapter(adapter);
Where details is an ArrayList> of my text. DetailAdapter has a getView method which adds text to the textview and inflates the layout.
I believe the problem may be with the <corners /> tag, which can be a bit buggy; such as the bottomRightRadius and bottomLeftRadius properties are reversed.
You can try using <corners android:radius="7dp"/> instead.
android: shape corners do not work when setting individual corners
Android - Can't create simple rectangle shape... UnsupportedOperationException?
I was able to fix the problem by refreshing the Detail Adapter more frequently; apparently the lag in the emulator was enough time for the views to compute but the physical device was too fast.

Categories