Android runs on variety of devices that offer different screen sizes and densities.
When ever we designing a User interface it should fit in all devices. Follow Some good practice that will help you while developing Universal builds.
So here are some good practices which developers can adapt which will make a lot of difference.
1) Designing the UI through XML
2) Designing the UI through Code
3) Keeping Some Good Coding Designs
1) The way you are Designing the UI through Xml.
When Ever you receive a wire frame or design document you need to decide what are the components that i can developed through XML. Designing the UI through XML is the best practice for Screen Compatibility.
Here are some good practices for designing the UI through XML
1) Do not use AbsoluteLayout in XML . Most Preferred is Relative Layout So that whole inner child views will be related to the parent or other neighboring view components.
Which will give a tight coupling between view components and they will be in right place irrespective of all screens.
NOTE: DON'T ALLOW ANY CHILD VIEWS OR COMPONENTS IN FREE FLOW MANNER
2) Don't use 'px' pixel hard coding in your xml always use 'dp' density pixel in XML's
3) Use Wrap_content and Fill_parent(match_parent) for your layout dimensions but in some situation if you strictly want to hardcode the layout dimensions then do it with 'dp'
4) Try to avoid too much usage of margins and paddings. Use it in wise manner (Eg: if you want to place a view in center use allign_center = true instead of giving top and left margins stuffs)
5) Don't Hard Code any text to the Graphics Unless it is kind of a rare font and Color. This will help to reduce the amount of graphics in the project.
NOTE : GRAPHICS AND THE UI WIDGETS WHICH WE ARE USING IN THE LAYOUTS SHOULD BE LOOSELY COUPLED
2) The way you are designing the UI through code.
Obviously you need to follow all the best practices which specified in XML designing. Additional one thing we need to keep in mind as you see in XML we are forced at some situation where we need to hard code the dimensions with 'dp'. Like that in code also we need to hard code in that case the value which is hard coded should be multiplied by the SCALE factor
SCALE is nothing but Getting the screen's density. And it can be derived from DisplayMeterics object
//Getting the screen density in runtime
final float SCALE= getResources().getDisplayMetrics().density;
low-density screen Scale = 0.75
medium-density screen Scale = 1.0
high-density screen Scale = 1.5
extra high-density screen Scale = 2.0
Usage: If you are setting some margins to a Layout params below you are hardcoding 25 make sure it is SCALED
//loginParams.setMargin(0,25,0,0); -not right
// loginParams.setMargin(0,(int)SCALE * 25,0,0);
and of course try to identify those components which can be reused in other screens, develop that UI as a separate components so that it can be reused which is a good practice.
If you are very good in JAVA OOPS concept then you can do lot of magics in code. You can apply POLYMORPHISM and INHERITANCE a lot while making reusable UI components through code
In xml also you can use <include> tag to including the reusable xml components. Eg: In some Navigational Apps you can see the top bar will be same in some screen. So all you can do is created the top bar as a separate XML and try to include in other screens using <include> tag.
<include layout=name />
3) Keeping Some Good Coding Designs
Now a days and also in future most of the android builds which is going to reside in market will be universal builds
In that case we developers will have some challenges which we need to overcome with some smart code design architecture . As you all know in android what ever resources we are using in the project whether it may be different types of drawable for several resolution or screen size or even layout for different stuffs . All these can be accessed in our code through R.java file. We need to utilize these and make our code in good format
If we are working on a universal build . We need to make lot of run times checks in the code in order to decide which layout to be loaded or which drawable to be loaded that kind of stuff.
Basically there will be a bunch of runtime checks to choose which resource should be loaded
In these kind of scenarios we need to be smart in such a way that in our code we need to keep 2 main files
say DeviceConfigurationManager.java
//This java file should be a single ton class which should be initialized in the entry point of your app and can be accessed across the application from any class maintaing same instance. In this we need all the helper functions to determine the physical environment where the app is going to interact such as screen size, device os version, resolution, screen height, screen width, device name, manufacturer name, and also you can write a small helper function in this file to determine what inch it is 10" or 7 or" or 8" what ever may be, try to add lot of helper functions by maximum utilization of Display Meterics class,Configuration Class etc in Android.
say ResourceSelectionManager.java
//This java file should be a single ton class which should be initialized in the entry point of your app and can be accessed across the application from any class mainting same instance.. This file mainly contains all the runtime checks in the application ,here you can write bunch of helper function that decides which resources should be loaded it will return unique int (which you can see in R.java) i.e., R.layout.lay_name or R.drawable.drw_name or what ever stuff, keep in mind don't return any View Object make sure it should return only the R.java reference ID (Unique Integer). If you return View Object itself it will lead to some memory leak.
e.g. :
if(//7inch pro){
setContentView(R.layout.loginview_7);
}
elseif(//7ich landscape){
setContentView(R.id.loginview_7_landscape);
}
elseif(10 inch por){
setContentView(R.id.loginview_10_landscape)
}
elseif(10 inch land){
setContentView(R.id.loginview_10_landscape)
}
here you can see trying to set a login layout with some runtime checks this is a single scenario when we are playing with universal build bunch of these kind of runtime checks will be there in the whole application which will mess up your code and make them very difficult to debug and maintain . If it is a big project then things will be more complicated. Instead of that all you have to do is
setContentView(ResourceSelectionManger.getInstance().getLoginView()); //
its enough the function will give you a unique integer that loads the appropriate resource.
you can then move your runtime checks into ResourceSelectionManger.getInstance().getLoginView(); function . Like this move all your runtimes checks into ResourceSelectionManager.java and give some good documentation to each function residing in this file. And enhance the importance of this file to a app configuration level. So when ever if you find any weird UI issue or functionality issues in some devices all you have to do is fetch the api docs of ResourceSelectionManager.java and find out the function . Put the debugger in that function and you can see what is the issue
This will give you a good control and maintenance over the code when we are developing universal builds.
NOTE: Also try to avoid hardcoding of Magic Numbers in the code . Suppose if you want to perform some operation if user touches on the middle of the screen
if(touch x==300 && y==200){ //wrong approach
//do this
}
its wrong always try to come up with some formula that determines this number
e.g. instead of 300 (getDeviceHeight/2) or what ever may be Construct a formula in such a way that it will work in all physical screen size.
Keep these kind of stuffs while coding it will help you a lot.
Regards
Roger
When ever we designing a User interface it should fit in all devices. Follow Some good practice that will help you while developing Universal builds.
So here are some good practices which developers can adapt which will make a lot of difference.
1) Designing the UI through XML
2) Designing the UI through Code
3) Keeping Some Good Coding Designs
1) The way you are Designing the UI through Xml.
When Ever you receive a wire frame or design document you need to decide what are the components that i can developed through XML. Designing the UI through XML is the best practice for Screen Compatibility.
Here are some good practices for designing the UI through XML
1) Do not use AbsoluteLayout in XML . Most Preferred is Relative Layout So that whole inner child views will be related to the parent or other neighboring view components.
Which will give a tight coupling between view components and they will be in right place irrespective of all screens.
NOTE: DON'T ALLOW ANY CHILD VIEWS OR COMPONENTS IN FREE FLOW MANNER
2) Don't use 'px' pixel hard coding in your xml always use 'dp' density pixel in XML's
3) Use Wrap_content and Fill_parent(match_parent) for your layout dimensions but in some situation if you strictly want to hardcode the layout dimensions then do it with 'dp'
4) Try to avoid too much usage of margins and paddings. Use it in wise manner (Eg: if you want to place a view in center use allign_center = true instead of giving top and left margins stuffs)
5) Don't Hard Code any text to the Graphics Unless it is kind of a rare font and Color. This will help to reduce the amount of graphics in the project.
NOTE : GRAPHICS AND THE UI WIDGETS WHICH WE ARE USING IN THE LAYOUTS SHOULD BE LOOSELY COUPLED
2) The way you are designing the UI through code.
Obviously you need to follow all the best practices which specified in XML designing. Additional one thing we need to keep in mind as you see in XML we are forced at some situation where we need to hard code the dimensions with 'dp'. Like that in code also we need to hard code in that case the value which is hard coded should be multiplied by the SCALE factor
SCALE is nothing but Getting the screen's density. And it can be derived from DisplayMeterics object
//Getting the screen density in runtime
final float SCALE= getResources().getDisplayMetrics().density;
low-density screen Scale = 0.75
medium-density screen Scale = 1.0
high-density screen Scale = 1.5
extra high-density screen Scale = 2.0
Usage: If you are setting some margins to a Layout params below you are hardcoding 25 make sure it is SCALED
//loginParams.setMargin(0,25,0,0); -not right
// loginParams.setMargin(0,(int)SCALE * 25,0,0);
and of course try to identify those components which can be reused in other screens, develop that UI as a separate components so that it can be reused which is a good practice.
If you are very good in JAVA OOPS concept then you can do lot of magics in code. You can apply POLYMORPHISM and INHERITANCE a lot while making reusable UI components through code
In xml also you can use <include> tag to including the reusable xml components. Eg: In some Navigational Apps you can see the top bar will be same in some screen. So all you can do is created the top bar as a separate XML and try to include in other screens using <include> tag.
<include layout=name />
3) Keeping Some Good Coding Designs
Now a days and also in future most of the android builds which is going to reside in market will be universal builds
In that case we developers will have some challenges which we need to overcome with some smart code design architecture . As you all know in android what ever resources we are using in the project whether it may be different types of drawable for several resolution or screen size or even layout for different stuffs . All these can be accessed in our code through R.java file. We need to utilize these and make our code in good format
If we are working on a universal build . We need to make lot of run times checks in the code in order to decide which layout to be loaded or which drawable to be loaded that kind of stuff.
Basically there will be a bunch of runtime checks to choose which resource should be loaded
In these kind of scenarios we need to be smart in such a way that in our code we need to keep 2 main files
say DeviceConfigurationManager.java
//This java file should be a single ton class which should be initialized in the entry point of your app and can be accessed across the application from any class maintaing same instance. In this we need all the helper functions to determine the physical environment where the app is going to interact such as screen size, device os version, resolution, screen height, screen width, device name, manufacturer name, and also you can write a small helper function in this file to determine what inch it is 10" or 7 or" or 8" what ever may be, try to add lot of helper functions by maximum utilization of Display Meterics class,Configuration Class etc in Android.
say ResourceSelectionManager.java
//This java file should be a single ton class which should be initialized in the entry point of your app and can be accessed across the application from any class mainting same instance.. This file mainly contains all the runtime checks in the application ,here you can write bunch of helper function that decides which resources should be loaded it will return unique int (which you can see in R.java) i.e., R.layout.lay_name or R.drawable.drw_name or what ever stuff, keep in mind don't return any View Object make sure it should return only the R.java reference ID (Unique Integer). If you return View Object itself it will lead to some memory leak.
e.g. :
if(//7inch pro){
setContentView(R.layout.loginview_7);
}
elseif(//7ich landscape){
setContentView(R.id.loginview_7_landscape);
}
elseif(10 inch por){
setContentView(R.id.loginview_10_landscape)
}
elseif(10 inch land){
setContentView(R.id.loginview_10_landscape)
}
here you can see trying to set a login layout with some runtime checks this is a single scenario when we are playing with universal build bunch of these kind of runtime checks will be there in the whole application which will mess up your code and make them very difficult to debug and maintain . If it is a big project then things will be more complicated. Instead of that all you have to do is
setContentView(ResourceSelectionManger.getInstance().getLoginView()); //
its enough the function will give you a unique integer that loads the appropriate resource.
you can then move your runtime checks into ResourceSelectionManger.getInstance().getLoginView(); function . Like this move all your runtimes checks into ResourceSelectionManager.java and give some good documentation to each function residing in this file. And enhance the importance of this file to a app configuration level. So when ever if you find any weird UI issue or functionality issues in some devices all you have to do is fetch the api docs of ResourceSelectionManager.java and find out the function . Put the debugger in that function and you can see what is the issue
This will give you a good control and maintenance over the code when we are developing universal builds.
NOTE: Also try to avoid hardcoding of Magic Numbers in the code . Suppose if you want to perform some operation if user touches on the middle of the screen
if(touch x==300 && y==200){ //wrong approach
//do this
}
its wrong always try to come up with some formula that determines this number
e.g. instead of 300 (getDeviceHeight/2) or what ever may be Construct a formula in such a way that it will work in all physical screen size.
Keep these kind of stuffs while coding it will help you a lot.
Regards
Roger
