Tuesday 31 January 2012

Setting external front or Typeface in android

In this tutorial i will show how you can use external fonts in your Android application instead of regular fonts.
The first step is that you need to download a front (.ttf file) from internet which you want to use. It's easy. You can search for free fonts and download the one which you want to use. Here in this tutorial we will be using two fonts - RockFont font and FeastOfFlesh font as shown below.

Now inside the assets folder of your project create a new folder and name it as fonts. Copy the font(.ttf) files in this folder. In our case the font files are RockFont.ttf and FEASFBRG.TTF.
If you are using Eclipse refresh your project directory tree once. Now copy the following code in the main.xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"                                                                                                                                          
    android:id="@+id/main_root" 
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:id="@+id/text1"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
   />
<TextView  
    android:id="@+id/text2"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    />
</LinearLayout>
Now if you want your TextViews to have this external front you need to perform the below code in your activity 
  @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Typeface font1 = Typeface.createFromAsset(getAssets(), "fonts/RockFont.ttf");
        Typeface font2 = Typeface.createFromAsset(getAssets(), "fonts/FEASFBRG.TTF");
        TextView customText1 = (TextView)findViewById(R.id.text1);
        TextView customText2 = (TextView)findViewById(R.id.text2);


        customText1.setTypeface(font1);     // to set the font
        customText1.setTextSize(40.f);        // to set the text size
        customText1.setText("Hello! This is a custom font...");   // to set the text to be displayed 
        
        customText2.setTypeface(font2);
        customText2.setTextSize(30.f);
        customText2.setText("Developed by www.bOtskOOl.com");
    }
The Typeface class specifies the typeface and intrinsic style of a font. We have created two objects of this class - font1 and font2 and assigned them the path of two font files by using creatFromAsset() method.
After this we declare two objects of TextView class and assign them the ids of our XML layout. We then define what type of font to use by using setTypeface() function. We can alter the default textsize by using setTextSize() method. And finally we define the text to be displayed via setText() method.
Now if you are working with a layout where you want to set custom font on multiple objects ,instead of calling all the TextView,EditText ,Button etc in your Activity you can simply use this method.First get the root view in your onCreate then call the method with this two parameters. 
Typeface font1 = Typeface.createFromAsset(getAssets(), "fonts/RockFont.ttf");  
ViewGroup rootVIew = (ViewGroup) findViewById(R.id.main_root);                                                                                                                                                           see  the id of LinearLayout in main.xml
public static void setTypeFaceForChilds(ViewGroup viewGroup,Typeface typeface) {
                          final int childCount = viewGroup.getChildCount();
                          for (int i = 0; i < childCount; i++) {
                         View view = viewGroup.getChildAt(i);
                                    if (view instanceof ViewGroup) {
                                  setTypeFaceForChilds((ViewGroup) view,typeface);
                                   } else if(view instanceof TextView){
                                              ((TextView) view).setTypeface(typeface);
                                               }
                            }
}
This is a recursive method it will get all the child's under the root layout and then set the  Typeface .It will not wor with Spinners.It will only wor on the ViewGroup child objects (TextView,EditText ,Button etc.)
Enjoy.... 
Do post your doubts, queries or suggestions in this blog.


Read file from Asset Folder in Android

In android application sometime we need to store files in our asset folder .I have used this method in many of my application and it works perfectly .To read a file from the Asset folder you just need to call this method  .


public static String ReadFromAssetFile(Context context,String filename) {

       String content = "";

      InputStream inputStream = null;

       try {
            inputStream = context.getAssets().open(filenames);
            BufferedReader readerRead1 = new BufferedReader
(new InputStreamReader(inputStream));
 String line="";
while((line=readerRead1.readLine())!=null){
content+=line.trim();
 }
} catch (IOException e1) {
// TODO Auto-generated catch block
return content;
 }
   return content;

}  


Enjoy.... 
Do post your doubts, queries or suggestions in this blog.

Sunday 29 January 2012

Android animation.Part-II


In this part we will focus on solving advance animation problems in Android. We have done simple animation in our previous tutorial now we will try create a more complex animation in a simpler way. We will create a simple animation that moves a Button from the top left corner of the screen to the center when it is clicked, then remains there, and when clicked again it moves back to its original position.

After you read the documentation http://developer.android.com/guide/topics/resources/animation-resource.h... it may seem easy to solve. We can define the animation relative to the parents size in percent (50%p), and the fillAfter attribute makes the button remain there, instead of jumping back to its original position. We can even define all of this in XML below.

      <?xml version="1.0" encoding="utf-8"?>
2       <translate xmlns:android="http://schemas.android.com/apk/res/android"
3          android:fromXDelta="0%p" android:fromYDelta="0%p"
4          android:toXDelta="50%p" android:toYDelta="50%p"
5          android:duration="1000"
6          android:fillAfter="true" />
But when you try this out, you will face two problems. First, the button will not be properly centered, the buttons top left corner will be in the center. Second, after it moved to the center it won’t be clickable any more. The clickable area of the button does not move with the animation, if you try to click at the original position of the button you will be able to trigger the onclick again. Unfortunately such a simple code, like the xml above will not be enough to fix these simple problem.
To properly center the button we must compute where the buttons top left corner should be. When the button is clicked get the buttons size, and its parent views size, compute where it should move, and create the proper animation by code. Somehow we have to track where the button is, if it is already in the middle, we have to reverse the animation. This can be done like this:
      public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
      final Button button = (Button) findViewById(R.id.button);
        final RelativeLayout mainContainer = (RelativeLayout)findViewById(R.id.mainContainer);
              button.setOnClickListener(new OnClickListener() {
           @Override
            public void onClick(View v) {
          //have to get the sizes here instead of onCreate, in onCreate size is not         //computed yet
          int buttonHeight = button.getHeight();
          int parentHeight = mainContainer.getHeight();
         int buttonWidth = button.getWidth ();
          int parentWidth  = mainContainer.getWidth();
       
        //detect if have to move to center, or already there and have to move back
         boolean isInCenter = button.getLeft()>0;
        final int fromX = isInCenter?(parentWidth/2)-(buttonWidth/2):0;
        final int fromY = isInCenter?(parentHeight/2)-(buttonHeight/2):0;
        final int toX = isInCenter?0:(parentWidth/2)-(buttonWidth/2);
        final int toY = isInCenter?0:(parentHeight/2)-(buttonHeight/2);
       
        //create the animation
            TranslateAnimation moveAnim = new TranslateAnimation(
            TranslateAnimation.ABSOLUTE, fromX, TranslateAnimation.ABSOLUTE, toX,
            TranslateAnimation.ABSOLUTE, fromY, TranslateAnimation.ABSOLUTE, toY);
                    moveAnim.setDuration(1000);
                    moveAnim.setFillAfter(true);

To solve the clickinkig problem we have to really move the button when the animation ended. This can be done by setting up an animation listener to detect the end of the animation. In the listener we set up margins to do the move. Because of this we have to remove this margins the next time we animate button or, the margins will mess it up. So we also add a listener to detect the start of the animation, and remove the margins there.


      moveAnim.setAnimationListener(new AnimationListener() {
        @Override
      public void onAnimationEnd(Animation animation) {
      //when the animation ended the button is really moved, to remain clickable
     LayoutParam params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
     params.leftMargin = toX;
     params.topMargin = toY;
     button.setLayoutParams(params);
          //remove the animation, its no longer needed, since button is really there
     button.clearAnimation();
    }
  
    @Override
    public void onAnimationStart(Animation animation) {
      //remove the margins used to really move the button, or it messes up the animation
    LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    params.leftMargin = 0;
    params.topMargin = 0;
    button.setLayoutParams(params);
    }
    @Override
    public void onAnimationRepeat(Animation animation) {
      //do nothing
    }
  });


Enjoy.... 
Do post your doubts, queries or suggestions in this blog.

Saturday 28 January 2012

Android basics of animation.Parrt-I

In android we have four  basic types of animations:
  • AlphaAnimation
  • RotateAnimation
  • ScaleAnimation
  • TranslateAnimation
This animations can be highly customized and combined, for example we can set the speed, delay, acceleration, duration of animations, then group them together in an AnimationSet.
Animations can be applyed as Layout animations to ViewGroups, to be triggered when the ViewGroup is created/displayed or applied to any view and be triggered by us any time.
The animations can be definex in XMl or by code. Defining in xml is mutch more clear, but you can not set animation parameters dinamically.
The animation XML files should be created in the res/anim folder and can be accessed using the R class, like R.anim.animation_name.
An animation defined in anim_jump.xml can look like this:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <set xmlns:android="http://schemas.android.com/apk/res/android">
  3.         <scale android:interpolator="@android:anim/accelerate_decelerate_interpolator"
  4.                 android:fromXScale="0.0" android:toXScale="1.4"android:fromYScale="0.0"
  5.                 android:toYScale="1.4" android:pivotX="50%"android:pivotY="50%"
  6.                 android:fillAfter="false" android:duration="700" />
  7.         <scale android:fromXScale="1.4" android:toXScale="0.8"
  8.                 android:fromYScale="1.4" android:toYScale="0.8"android:pivotX="50%"
  9.                 android:pivotY="50%" android:startOffset="700"android:duration="400"
  10.                 android:fillBefore="false" />
  11. </set>

The set tag can contain one or more animation definitions that will be applied at the same time, so if you want to play them after each other you can set a startOffset value for the second one.
This animation can be played on any view with a code like this:
  1. final Button button3 = (Button) findViewById(R.id.button3);
  2. button3.startAnimation(AnimationUtils.loadAnimation(Main.this, R.anim.anim_jump));

The exapmle below shows the creation of an animation without an XML file:
  1. //parameters set to do a full circle around its center
  2. RotateAnimation rotateAnimation = newRotateAnimation(0,360,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
  3. rotateAnimation.setDuration(500);
  4. rotateAnimation.setRepeatCount(2);
  5. //you can set many other parameters here
  6. final Button button1 = (Button) findViewById(R.id.button1);
  7. button1.startAnimation(rotateAnimation);

Creating complex animation sets are mutch more clean in XML, the example below creates an animation set from 3 animations by code:
  1. AnimationSet animationSet = new AnimationSet(true);
  2.                                
  3. RotateAnimation rotateAnimation = newRotateAnimation(0,360,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
  4. rotateAnimation.setDuration(500);
  5. rotateAnimation.setRepeatCount(2);
  6.                                
  7. animationSet.addAnimation(rotateAnimation);
  8.                                
  9. TranslateAnimation translateAnimation = new TranslateAnimation(0, 400, 0, 0);
  10.                                
  11. //setting offset and duration to start after first rotation completed, and end at the same time with the last roration
  12. translateAnimation.setStartOffset(500);
  13. translateAnimation.setDuration(1000);
  14.                                
  15. animationSet.addAnimation(translateAnimation);
  16.                                
  17. AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
  18. alphaAnimation.setStartOffset(500);
  19. alphaAnimation.setDuration(1000);
  20.                                
  21. animationSet.addAnimation(alphaAnimation);
  22. final Button button2 = (Button) findViewById(R.id.button2);
  23. button2.startAnimation(animationSet);

If we want do apply the animation already defined in anim_jump.xml as a layout animation, to play on all element in the group we need one more XML file in the res/anim folder to define this animation as a layout animation. Lets name this file as main_layout_animation.xml:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:animation="@anim/anim_jump&quot; />

After this we can apply this animation to a viewGrop, for example to a LinearLayout:
  1. LinearLayout mainContainer = (LinearLayout) findViewById(R.id.mainContainer);
  2. LayoutAnimationController controller =AnimationUtils.loadLayoutAnimation(this, R.anim.main_layout_animation);
  3. mainContainer.setLayoutAnimation(controller);


Enjoy.... 
Do post your doubts, queries or suggestions in this blog.