Android : Navigation button show wrong side when layout direction is RTL - android

I asked this question before (here) but nobody answered so I ask It a little bit simpler.
The problem is when I change the layout direction to RTL
(in
xml file : android:layoutDirection="rtl"
or programmatically :
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
getWindows().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
}
doesn't matter) the navigation icon remain LTR
How can I fix this issue?
To be more specific the arrow should point at right!

In the Activity Class -->
Add these lines :
onCreate(){
ActionBar ab = getSupportActionBar();
// Enable the Up button
ab.setDisplayHomeAsUpEnabled(true);
ab.setBackgroundDrawable(getResources().getDrawable(R.drawable.ic_arrow_back_black_24dp, getApplicationContext().getTheme()));
}
#Override
public void onBackPressed() {
super.onBackPressed();
Intent login = new Intent(LoginActivity.this, MainActivity.class);
login.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(login);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
Write a custom drawable using File--> New--> VectorAsset
https://developer.android.com/studio/write/vector-asset-studio.html
Choose the arrow accordingly and Enable the field -->(Enable the auto mirroring for RTL Layout)
Auto-Mirror Property checked
I have changed the color of Arrow to be White, You can choose your own color
FileName: ic_arrow_back_black_24dp.xml in drawable folder
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#00000000"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
</vector>
After changing the Locale to Arabic - which changes the entire Layout from RTL to LTR

I just added a drawable icon that rotated 180 degree and set the icon in onCreate() but the problem is we should do this in every activity that It's layout is RTL. So if our application supports both directions we should check if layout direction is RTL then change the up indicator:
if(config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_arrow_up_rtl);
}

There is property called auto mirror which itself rotate the icon on the basis of locale .
If you are using Toolbar and added the icon as navigation icon , then use the below line to rotate the icon
toolbar.navigationIcon?.isAutoMirrored = true
If you are using image view , then just add a style to the image view to rotate icon . Do create a different style for arabic .
In your style file add the following code :
<style name="ImageMirror">
<item name="android:scaleX">-1</item>
</style>
Go for the vector drawables as they default have this auto mirror property .

u can use :
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_arrow_forward_24dp);
and Add RTL arrow to drawable

The problem is because the arrow is not following the RTL situation of the app
I had the same problem and I ended up creating a custom toolbar
use a NoActionBar theme and create an empty with only android.support.v7.widget.Toolbar in it
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toolbar"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary">
</android.support.v7.widget.Toolbar>
then include it in all activities needing a toolbar
<include layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent" />
and in activity do this
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if(toolbar != null) {
setSupportActionBar(toolbar);
toolbar.inflateMenu(R.menu.whatever);
}
the custom one will follow the RTL direction of the app

I had same problem with Animation, and I resolved it! As I noticed, it is bug for versions below KitKat(and for sure above 4.2, include).
What you need to do, as was said here, it is rotate for 180 in right place.
You have to create your own ActionBarDrawerToggle based on the given code by Google. Inside you will find class DrawerArrowDrawableToggle - it is custom Drawable, that draw Arrow/Humberger "animation". Like before you have to create your own class, based on the code of DrawerArrowDrawableToggle, and inside you will find variable "flipToPointRight" and take care that it will be "RIGHT" and you have take care that rotation won't work on versions >= Kitkat, otherwise will have the problem there. It is all.

This bug happens on Android 4.2 (API 17) only, when using the AppCompat support library version 24 or above.
In previous support library versions like:
compile 'com.android.support:appcompat-v7:23.0.1'
... It was handled automatically, because this older library contained the drawable images of the arrow facing both left and right:
R.drawable.abc_ic_ab_back_mtrl_am_alpha (This is inside the AppCompat v23 library, and multiple versions were available in drawable and drawable-ldrtl, ...)
You can see these images in Android Studio -> View -> Tool Windows -> Project -> Select "Project" in the drop-down menu -> appcompat-v7-23.0.1 -> res -> drawable -> ...
In newer versions of AppCompat, such as
compile 'com.android.support:appcompat-v7:24.0.0' // or anything above 23
The arrow image now only exists as a single vector drawable pointing towards the left:
R.drawable.abc_ic_ab_back_material (Vector XML file inside AppCompat v24 library)
And Android 4.2 does not seem to be able to mirror it in the opposite direction for RTL mode. And the library does not contain a fallback image.
So a potential way to fix it, without creating your own custom image, is to use the older AppCompat support library version 23 or below. But this may not be compatible with newer tools/libraries.

As far as I know this happens in all android studio versions. Luckily, the solution is easier than you think. You just need to disable RTL support. Just go to your Manifest file and change the value in this line to False: android:supportsRtl="true". Another good thing is that this solution will solve most of the problems that occur in RTL languages like Arabic. Hope this helps (:

Related

How can i change the StatusBar color or set it to transparent on Android, using NativeScript with Angular?

I'm using NativeScript with Angular, and I can't seem to change the StatusBar color in my project or set it to transparent (any of these would be fine). Instead, it is not totally transparent, but is translucent black, so the background scrolls behind it but it is darkened by the StatusBar. I would like to set it to transparent or to change the color (to the same one as the page background)
What I've tried:
Changing the "ns_primaryDark" and "ns_primary" colors in App_Resources/Android/src/main/res/values/colors.xml (works on launch screen if i set the TranslucentStatus" to false;
Setting <item name="android:windowTranslucentStatus"></item> in <style name="AppThemeBase" parent="Theme.AppCompat.Light.NoActionBar"> in App_Resources/Android/src/main/res/values/styles.xml doesn't make any difference, despite working fine on <style name="LaunchScreenThemeBase" parent="Theme.AppCompat.Light.NoActionBar"> (the launch screen);
Setting <item name="android:windowLightStatusBar">true</item> changes the text color to black and works on both the launch screen and the main app;
Using the code below in any component's constructor doesn't change anything in my app, but it worked on the other project i tried (details below), setting the color to black:
let window = app.android.startActivity.getWindow();
window.setStatusBarColor(new Color("black").android);
One thing i also tried was doing these steps on another project i had downloaded (https://github.com/NativeScript/nativescript-ui-samples/tree/master/chart this one, to be exact) and it worked, so i thought the template i used in my application might be "overlaying" any settings for the StatusBar.
I then tried to make a new project with the same template as mine and i figured out that it didn't work either. Is the template my problem? If so, is there any way to get around it?
The template i used is this one: https://github.com/NativeScript/nativescript-app-templates/tree/master/packages/template-tab-navigation-ng (also works with "tns create my-app-name --template tns-template-tab-navigation-ng").
Big thanks in advance.
Add the following code to your main.ts, that should do the job.
import * as application from "tns-core-modules/application";
declare var android;
application.android.on(application.AndroidApplication.activityCreatedEvent, (event) => {
const activity = event.activity;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
activity.getWindow().setStatusBarColor(android.graphics.Color.TRANSPARENT);
} else {
activity.getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
const parent = activity.findViewById(android.R.id.content);
for (let i = 0; i < parent.getChildCount(); i++) {
const childView = parent.getChildAt(i);
if (childView instanceof android.view.ViewGroup) {
childView.setFitsSystemWindows(true);
childView.setClipToPadding(true);
}
}
});
It's pretty much as in the library. If you like to use the library, you will have to include it in your app grad and access the StatusBarUtil class.
You can use this library to transparent your status bar Library
compile 'com.jaeger.statusbarutil:library:1.4.0'
To make any specific activity to transparent you can simply use this
StatusBarUtil.setTransparent(Activity activity)
It will look like this

Inline sdk version check in Android XML?

Sometimes, when I want to add SDK 21+ feature to my layout, I need to create whole layout in another file. It's heavy to me because I want to do or check everything in one layout. More of layouts are looking complex and hard to manage. Instead of having two layouts for different SDK versions, can I do something like this:
<ImageView
android:id="#+id/x"
android:layout_width="16dp"
android:layout_height="wrap_content"
<compatibility sdk_higher_than="21">
android:elevation="xdp" //my problem not about the elevation. Its just an example that pops in my mind about the compatibility.
</compatibility>
app:srcCompat="#drawable/ic_x" />
I can make this stuff programmatically but when I should see the view instantly on designer, making it programmatically is not a good way for me. If there is a good practice or idea for this problem can anybody illuminate me?
Yes you can do that by adding tool target API:
First add: <RootTag xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >
Example:
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:targetApi="14" >
or by name: tools:targetApi="jelly_bean"
If you want your layout directries to be use in different versions, name your files as:
/res/layout/layout.xml - (default directries)
/res/layout-v14/layout.xml
/res/layout-v17/layout.xml
Also, if you want to dynamically create element in your code:
You can also use annotations in your java code to make things easy:
First import: import android.annotation.TargetApi;
Then, use this annotation above your method:
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
There are more annotation that you can get help:
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
Above annotation to warn for methods that are used lower API level. Read more about requiresApi: Android API level annotation for Android libraries
Now, inside your method you can dynamically generate views.
Example from the doc:
private void setUpActionBar() {
// Make sure we're running on Honeycomb or higher to use ActionBar APIs
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
Read doc for more details about annotations: https://developer.android.com/studio/write/annotations
You can not give your view elevation in your XML and check for your SDK version in your code - if it's over 21 give the view elevation programmatically.
For example:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
//the API level is above 21 and you can manipulate your view with all the features that available to API level 21+
}

Using android vector Drawables on pre Lollipop crash

I'm using vector drawables in android prior to Lollipop and these are of some of my libraries and tool versions:
Android Studio : 2.0
Android Gradle Plugin : 2.0.0
Build Tools : 23.0.2
Android Support Library : 23.3.0
I added this property in my app level Build.Gradle
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
It is also worth mentioning that I use an extra drawable such as LayerDrawable(layer_list) as stated in Android official Blog (link here) for setting drawables for vector drawables outside of app:srcCompat
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/search"/>
</level-list>
You’ll find directly referencing vector drawables outside of
app:srcCompat will fail prior to Lollipop. However, AppCompat does
support loading vector drawables when they are referenced in another
drawable container such as a StateListDrawable, InsetDrawable,
LayerDrawable, LevelListDrawable, and RotateDrawable. By using this
indirection, you can use vector drawables in cases such as TextView’s
android:drawableLeft attribute, which wouldn’t normally be able to
support vector drawables.
When I'm using app:srcCompat everything works fine, but when I use:
android:background
android:drawableLeft
android:drawableRight
android:drawableTop
android:drawableBottom
on ImageView, ImageButton, TextView or EditText prior to Lollipop, it throws an expection:
Caused by: android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9
LATEST UPDATE - Jun/2019
Support Library has changed a bit since the original answer. Now, even the Android plugin for Gradle is able to automatically generate the PNG at build time. So, below are two new approaches that should work these days. You can find more info here:
PNG Generation
Gradle can automatically create PNG images from your assets at build time. However, in this approach, not all xml elements are supported. This solution is convenient because you don't need to change anything in your code or in your build.gradle. Just make sure you are using Android Plugin 1.5.0 or higher and Android Studio 2.2 or higher.
I'm using this solution in my app and works fine. No additional build.gradle flag necessary. No hacks is necessary. If you go to /build/generated/res/pngs/... you can see all generated PNGs.
So, if you have some simple icon (since not all xml elements are supported), this solution may work for you. Just update your Android Studio and your Android plugin for Gradle.
Support Library
Probably, this is the solution that will work for you. If you came here, it means your Android Studio is not generating the PNGs automatically. So, your app is crashing.
Or maybe, you don't want Android Studio to generate any PNG at all.
Differently from that "Auto-PNG generation" which supports a subset of XML element, this solution, supports all xml tags. So, you have full support to your vector drawable.
You must first, update your build.gradle to support it:
android {
defaultConfig {
// This flag will also prevents Android Studio from generating PNGs automatically
vectorDrawables.useSupportLibrary = true
}
}
dependencies {
// Use this for Support Library
implementation 'com.android.support:appcompat-v7:23.2.0' // OR HIGHER
// Use this for AndroidX
implementation 'androidx.appcompat:appcompat:1.1.0' // OR HIGHER
}
And then, use app:srcCompat instead of android:src while loading VectorDrawables. Don't forget this.
For TextView, if you are using the androidx version of the Support Library, you can use app:drawableLeftCompat (or right, top, bottom) instead of app:drawableLeft
In case of CheckBox/RadioButton, use app:buttonCompat instead of android:button.
If you are not using the androidx version of the Support Library and your minSdkVersion is 17 or higher or using a button, you may try to set programmatically via
Drawable icon = AppCompatResources.getDrawable(context, <drawable_id>);
textView.setCompoundDrawablesWithIntrinsicBounds(<leftIcon>,<topIcon>,<rightIcon>,<bottomIcon>);
UPDATE - Jul/2016
They re-enabled that VectorDrawable in
Android Support Library 23.4.0
For AppCompat users, we’ve added an opt-in API to re-enable support Vector Drawables from resources (the behavior found in 23.2) via AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) - keep in mind that this still can cause issues with memory usage and problems updating Configuration instances, hence why it is disabled by default.
Maybe, build.gradle setting is now obsolete and you just need to enable it in proper activities (however, need to test).
Now, to enable it, you must do:
public class MainActivity extends AppCompatActivity {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
...
}
Original Answer - Apr/2016
I think this is happening because Support Vector was disabled in the latest library version: 23.3.0
According to this POST:
For AppCompat users, we’ve decided to remove the functionality which let you use vector drawables from resources on pre-Lollipop devices due to issues found in the implementation in version 23.2.0/23.2.1 (ISSUE 205236). Using app:srcCompat and setImageResource() continues to work.
If you visit issue ISSUE 205236, it seems that they will enable in the future but the memory issue will not be fixed soon:
In the next release I've added an opt-in API where you can re-enable the VectorDrawable support which was removed. It comes with the same caveats as before though (memory usage and problems with Configuration updating).
I had a similar issue. So, in my case, I reverted all icons which use vector drawable from resource to PNG images again (since the memory issue will keep happening even after they provide an option to enable it again).
I'm not sure if this is the best option, but it fixes all the crashes in my opinion.
I had the same problem.
But doing a lot of R&D I got the answer.
For Imageview and ImageButton use,app:srcCompat="#drawable/...."
and for other views like Button, Textview, instead of using "drawableLeft/right..." in the XML, specify drawables programmitically as :
button.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(mContext,R.drawable.ic_share_brown_18dp), null, null, null);
And use "AppCompatResources" to get the drawable.
To elaborate on the other very good answers, here is a diagram that can help you. It is valid if you have Support Library from 23.4.0 to at least 25.1.0.
The answer from Guillherme P is pretty awesome. Just to make a small improvement, you don't need to add that line in every activity, if you added it once in the Application class it will work as well.
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
REMEMBER: You still need to have enabled the use of the support library in gradle:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
Also, make sure you are using a support library version greater than v23.4, when Google added back the support for Drawable Containers for VectorDrawables (release note)
Update
And for code changes:
Make sure to update to app:srcCompat every place that accepts the android:src attribute (the IDE will warn you if it's invalid like for the <bitmap> tag).
For drawableLeft, drawableStart, drawableRight, drawableEnd attributes used in TextView and similar views, you will have to set them programmatically for now. An example of setting drawableStart:
Drawable drawable = AppCompatResources.getDrawable(
getContext(),
R.drawable.your_vector_drawable);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
textView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null);
}
I had the same problem. And fix it by removing
vectorDrawables.useSupportLibrary = true
My target version is 25 and support library is
compile 'com.android.support:appcompat-v7:25.3.1'
VectorDrawables on pre-lollipop should work fine without using
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
If you want to use VectorDrawables inside ImageViews, you can use the attribute srcCompat and it will work, but inside Buttons or TextViews it won't, so you need to wrap the Drawable into an InsetDrawable or a LayerDrawable. There is another trick I discovered, if you are using data binding, you could do this:
android:drawableLeft="#{#drawable/vector_ic_access_time_24px}"
android:drawableStart="#{#drawable/vector_ic_access_time_24px}"
That will magically work, I haven't investigated what's happening behind the scenes, but I guess the TextView is using the getDrawable method from the AppCompatResources or similar.
Lot of R & d, finally getting this solution for crashes on pre-lollipop devices.
For Imageview
use app:srcCompat instead of android:src
For TextView/EditText
Remove drawableleft,drawableright.... and set from drawable java code.
txtview.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(EventDetailSinglePage.this,
R.drawable.ic_done_black_24_n), null, null, null);
For Build.gradle
vectorDrawables.useSupportLibrary = true
Easiest way use :
app:drawableRightCompat ="#drawable/ic_mobilelogin"
app:drawableEndCompat="#drawable/ic_mobilelogin"
app:srcCompat="#drawable/ic_mobile"
and... just use app:**Compatfor compatability.
Also add support on build.gradle (module)
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
For anyone who upgrade to android gradle 3.0 and above, there is no need to use AppCompatDelegate.setCompatVectorFromResourcesEnabled(true), or set vectorDrawables.useSupportLibrary = true (add this will cause problem) and use app:srcCompat, it just works.
Take me two days to figure this out, and have not find any related docs in google's docs...
After using the below code.
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}}
still, vector images issue exists for below attributes are
DrawableEnd,
DrawableStart,
DrawableTop,
DrawableBottom,
Background
In this case, please follow as below, Instead of referencing vector image directly use selector tag as an intermediate drawable file.
Example:
ic_warranty_icon.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="17dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="17"
android:viewportHeight="24">
<path
android:fillColor="#fff"
android:pathData="M10.927,15.589l-1.549,0.355a7.47,7.47 0,0 1,-0.878 0.056c-4.136,0 -7.5,-3.364 -7.5,-7.5s3.364,-7.5 7.5,-7.5 7.5,3.364 7.5,7.5c0,3.286 -2.126,6.078 -5.073,7.089zM8.5,2a6.508,6.508 0,0 0,-6.5 6.5c0,3.583 2.917,6.5 6.5,6.5s6.5,-2.917 6.5,-6.5 -2.917,-6.5 -6.5,-6.5z" />
safe_ic_warranty_icon.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ic_warranty_icon" />
</selector>
Your TextView/Layout.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="#drawable/ic_warranty_icon"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/ic_warranty_icon"
/>
I am using VectorDrawables on Pre-lollipop devices and this is how I do it :-
Step 1:
Put this in your app level gradle.
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
Step 2:
Put this in your Application class and don't forget to register your Application class in the manifest file.
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
}
Step 3:
Get VectorDrawables using,
imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.my_vector_drawable));
We tried 3 things
vectorDrawables.useSupportLibrary = true
Setting setCompatVectorFromResourcesEnabled in Application class
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
And use app:srcCompat
But even after that it was failing with
Resources$NotFoundException: File res/drawable/$my_icon__0.xml from color state list resource ID #0x7f080008
then we figured out that our SVG had a Gradient tag.
Converting the gradient tag to individual paths for below API <= 23 and using the same SVG API >= 24 worked.
Got help from this answer https://stackoverflow.com/a/47783962/2171513
I was struggling with this for hours.
I tried everything these answers told me to, but my app didn't stop crashing. I deleted this line: app:srcCompat="#drawable/keyboard" and my app stopped crashing. and then when I added this same thing back, it started crashing again. So I decided to open that file and I saw an error at the first line saying
"The drawable 'Keyboard' has no declaration in the base drawable
folder; this can lead to crashes.
I right-clicked the file and clicked "Show in explorer" and it was not in the drawable folder but in the drawable-v24 directory. So I copied it and pasted to the drawable directory and finally got rid of crashes.
Simply overlap vector drawable to state-list then problem will be solved
For example you have back arrow vector image:
ic_back_arrow.xml
yes, you should overlap it to layer list xml (ic_back_arrow_vector_vector.xml):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ic_back_arrow"/>
</layer-list>
Because logic:
vectorDrawables.useSupportLibrary = true
and
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
will not help you on the some China devices and older samsung devices. If you do not overlap them, it will fail.
In my case, I was using a TabLayout, which I configured as it :
TabLayoutMediator(tabLayout!!, viewPager!!) { tab, position ->
if (position == 0)
tab.icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_list, theme)
else
tab.icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_building_map, theme)
}.attach()
The app was crashing at line tab.icon = ...
I change these to tab.setIcon(R.drawable.my_vector_asset), as it :
TabLayoutMediator(tabLayout!!, viewPager!!) { tab, position ->
if (position == 0)
tab.setIcon(R.drawable.ic_list)
else
tab.setIcon(R.drawable.ic_building_map)
}.attach()
And it worked !
Guilherme P's suggestion was not working for me. I went ahead and made the decision to use png's where I need to do things outside of app:srcCompat i.e. drawableLeft, drawableRight, etc. This was a pretty easy change to make, and doesn't have the potential memory issues AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
introduces.
An alternative to Benny's answer is to create an Activity superclass:
public abstract class VectorDrawableActivity extends AppCompatActivity {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
//...
}
Now extend VectorDrawableActivity instead of AppCompatActivity.

How do I create the semi-transparent grey tutorial overlay in Android?

You know when you run an Android device for the first time (something you see a lot if you use the emulator) that there's a helpful little tutorial about how to use the launcher and add widgets, etc. I'm trying to find an example of this on Google, but I can't. I'm hoping you know what I mean. It's the one with the blue "okay" buttons at each step.
Anyway, I want to create one for my app, but I'm not sure which is the best way to go about doing it.
Do I create a Fragment that I can make semi-transparent on top of my regular activity and have it show up on only the first run?
Do I make a semi-transparent .png for each section of the tutorial and overlay it over the regular launcher activity on the first run?
If I do the latter, how can I adjust for all the various screen sizes? I could just render the image in Photoshop to various dimensions, but that won't cover all of them. If I go the fragment route, I can just say "match_parent" and not worry about it. But then I have to figure out how Fragments work, and they confuse the hell out of me.
I think this open-source library is exactly what you're looking for:
Showcase View
You can grab the source code and setup instructions from GitHub.
Use a hexadecimal color code, which consists of two digits for alpha and six for the color itself, like this:
android:background="#22FFFFFF"
It'll make it semi-transparent.
android:background="#c0000000" for more darkness
Edited
Generally hexadecimak color code structure is like '#FFFF'
For attaining transparency add two digits after '#' to any color code.
Eg : #110000, #220000, #330000.
The greater those two digits, the lesser transparency.
You can try something like this
<LinearLayout ... >
<!-- your Normal layout goes here -->
<RelativeLayout android:id="#+id/tutorialView" android:background="#D0000000"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView android:src="#drawable/hint_menu" android:layout_alignParentLeft="true"
android:layout_centerVertical="true" android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
</LinearLayout>
And in your onCreate method
View tutorialView = findViewById(R.id.tutorialView);
boolean tutorialShown = PreferenceManager.getDefaultSharedPreferences(MainActivity.this).getBoolean(Constants.PREF_KEY_TUT_MAIN, false);
if (!tutorialShown) {
tutorialView.setVisibility(View.VISIBLE);
} else {
tutorialView.setVisibility(View.GONE);
}
tutorialView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.setVisibility(View.GONE);
PreferenceManager.getDefaultSharedPreferences(MainActivity.this).edit().putBoolean(Constants.PREF_KEY_TUT_MAIN, true).commit();
}
});
There is an award-winning library for this called "FancyShowcaseView":
https://github.com/faruktoptas/FancyShowCaseView
Add to your project like this:
In the top-level build.gradle (not the module level):
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}
In the module-level (app) build.gradle
dependencies {
compile 'com.github.faruktoptas:FancyShowCaseView:1.0.0'
}
Then you can call:
new FancyShowCaseView.Builder(this)
.focusOn(view)
.title("Focus on View")
.build()
.show();
You don't need to use Photoshop. You can Use for example a LinearLayout with android:background="#50134BE8". This will make it transparent blue. You can place the layout on top of everything and hide it when the user is done. You can use any background color, but to make it transparent, place a number from 01 to FE, after the "#" symbol to change its transparency. Set the width and the height to fill_parent to occupy the whole area. Place this view directly in the main layout. Hope this helps.

ActionBar with support library and Fragments overlay content

I added the android-support-library-v7-appcompat to my project to support ActionBar from API level 7 above.
It works like a charm on android 4.0+ and also on android 2.3 with a normal Activity that has setContentView in onCreate, but when the activity is loading an Fragment in onCreate the ActionBar gets overlapped with the content of my layout. At all other scenarios the ActionBar works well.
Here is some code:
class AssetsActivity extends ActionBarActivity{
#Override
protected void onCreate(Bundle arg0)
{
super.onCreate(arg0);
OpenLocalFragment assets = OpenLocalFragment.newInstance(index);
assets.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, assets).commit();
}
}
The theme of this activity is set in the manifest to:
#style/Theme.AppCompat
An this is the result on android 2.3 (on 4.0+ the ActionBar shows well)
You can se that the first lisview item is overlaping the ActionBar(White round icon and title "My activity")
It is possible that i found a bug in the support library, it is released only for 2 days now?
Thanks to all.
Edit:
This is now officially fixed and released in the Support Library v19.
As JJD commented below, you can use normally android.R.id.content with appcompat-v7 r.19.0.0 or newer. The home button works too.
With other words: The workaround below is no more needed if you use version 19.0.0 or newer.
I got the answer at code.google.com. i've made a summary from frederic's answer:
For pre ICS devices you must use:
R.id.action_bar_activity_content
instead of
android.R.id.content
R.id.action_bar_activity_content is a new id used in layout for displaying app content, it would appear that it replace android.R.id.content when you use support v7 appcompat ActionBarActivity.
You can use this code to retrieve the correct id of the activity content :
public static int getContentViewCompat() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH ?
android.R.id.content : R.id.action_bar_activity_content;
}
Thanks to frederic
Another alternative if you do not want to modify the source code of android-support-library-v7-appcompat is to add an empty layout in the layout xml file such as:
<LinearLayout
android:id="#+id/content_view"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
and make the fragment call to add to that layout instead:
ft.add(R.id.content_view, mFragment, mTag);
Seems a bit late to contribute but I had the same problem and haven't seen the answer here....
Check your styles.xml file, there might be an xml attribute for overlaying the actionbar set to true ie
true
The whole entry looks something like this
<item name ="actionBarTabTextStyle" > #style/TabTextStyle</item>
<item name = "windowActionBarOverlay">true</item>
If that is the case then just change the value of "windowActionBarOverlay" to false.
Add a extra empty list header with the size of the actionbar. Should be a good workaround.

Categories

Resources