Wednesday, 10 December 2014

Am I need to create duplicate XML files to support backward compatibility for styling the app?



I am trying to find a way to write less and more easy-to-understand styles for Android. Sometimes I am struggling to debug and I am loosing many hours just to find out why one of the actionbar's view does not have the correct text color (this was an example).


I think you know what I'm trying to say... you have the two XML files opened (one in left, the other on the right side of your IDE) and you are trying to identify each XML tag and you are applying different layout attributes to support backward compatibility for older versions of Android.


Let's take an example: customizing the actionbar.


Our manifest file:



<application
name="com.app.App"
theme="@style/AppTheme.NoActionBar" > ...


Currently, you need to create two (or more) XML files to apply the following attributes to your actionbar:


API <= 10



res/values/themes.xml




<style name="AppTheme.NoActionBar" parent="@style/Theme.AppCompat.Light">
<item name="windowActionBar">false</item>
</style>


API > 10



res/values-v11/themes.xml




<style name="AppTheme.NoActionBar" parent="@style/Theme.AppCompat.Light">
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>


This way we removed the actionbar from the activity. However, this is not complete, because on API <= 10, the screen isn't in full screen as on API > 10. You will see the app's label in the top of your activity. So, to have the same design on the two different devices, you need to add more code to your activity:



@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}


This was a small example, but this is way more complicated when you have many, many more styles declared in your files. At some point you will get lost.


What I'm trying to do is to simplify the work.


Can I merge the XML files without compile error and without duplicating the XML files?



res/values-v11/themes.xml




<style name="AppTheme.NoActionBar" parent="@style/Theme.AppCompat.Light">
<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="windowActionBar">false</item>
</style>


The above code won't work on API <= 10, but the code below does:



res/values/themes.xml




<style name="AppTheme.NoActionBar" parent="@style/Theme.AppCompat.Light">
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>

<item name="windowActionBar">false</item>
</style>


The above code is working, but some attributes is requiring the Android's namespace: android:tag. Otherwise, your IDE won't compile your project.


So, to suppress the errors, we can use xmlns:tools, which will remove the lint errors, and you can compile your code. However, you may also need to apply the tools:targetApi="lvl" attribute too:



res/values/themes.xml




<resources xmlns:tools="http://ift.tt/LrGmb4">
<style name="AppTheme.NoActionBar" parent="@style/Theme.AppCompat.Light">
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar" tools:targetApi="11">false</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>

<item name="windowActionBar">false</item>
</style>
</resources>


This way it's much more easier to maintain your code, and you will write less code than creating N xml files. However, sometimes, things are getting much more complicated, when you have more than 500+ lines in your XML file. The worst part is, the IDE won't show you any warnings or errors, the project can be compiled, but on different Android versions the layout will be different.


Finally... is there any way to write less and much more maintainability code?


No comments:

Post a Comment