Saturday, September 29, 2012

execute AsyncTask with series of parameters to load image(s) from internet

The previous example describe how to "Load Bitmap from internet in background thread using AsyncTask" to load ONE image only. If you have to load 10 images, is it need to create 10 AsyncTasks? obviously NO.

It can be noticed that the parameters passed to doInBackground() method is URL... urls, a series of parameter. In order to pass data to doInBackground(), put them in execute() call of AsyncTask object.

Here is the modified code to load 5 images from internet in AsyncTask, and update ImageViews and ProgressBar on the run, in onProgressUpdate() method.

execute AsyncTask with series of parameters to load image(s) from internet


package com.example.androidcolor;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;

public class MainActivity extends Activity {
 
 ProgressBar loadingProgressBar;
 ImageView[] targetImage = new ImageView[5];

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        targetImage[0] = (ImageView)findViewById(R.id.target0);
        targetImage[1] = (ImageView)findViewById(R.id.target1);
        targetImage[2] = (ImageView)findViewById(R.id.target2);
        targetImage[3] = (ImageView)findViewById(R.id.target3);
        targetImage[4] = (ImageView)findViewById(R.id.target4);
        
        loadingProgressBar = (ProgressBar)findViewById(R.id.loadingprogress);
        
        //Load bitmap from internet
        //As a example, I make all images load from the same source
        String onLineImage0 = "http://goo.gl/1VArP";
        String onLineImage1 = "http://goo.gl/1VArP";
        String onLineImage2 = "http://goo.gl/1VArP";
        String onLineImage3 = "http://goo.gl/1VArP";
        String onLineImage4 = "http://goo.gl/1VArP";
        URL onLineURL0, onLineURL1, onLineURL2, onLineURL3, onLineURL4;
        
  try {
   onLineURL0 = new URL(onLineImage0);
   onLineURL1 = new URL(onLineImage1);
   onLineURL2 = new URL(onLineImage2);
   onLineURL3 = new URL(onLineImage3);
   onLineURL4 = new URL(onLineImage4);
   new MyNetworkTask(5, targetImage, loadingProgressBar)
    .execute(onLineURL0, onLineURL1, onLineURL2, onLineURL3, onLineURL4);
  } catch (MalformedURLException e) {
   e.printStackTrace();
  }
        
    }
    
    private class MyNetworkTask extends AsyncTask<URL, Integer, Void>{
     
     ImageView[] tIV;
     Bitmap[] tBM;
     ProgressBar tProgressBar;
     
     public MyNetworkTask(int numberOfImage, ImageView[] iv, ProgressBar pb){
      
      tBM = new Bitmap[numberOfImage];
      
      tIV = new ImageView[numberOfImage];
      for(int i = 0; i < numberOfImage; i++){
       tIV[i] = iv[i];
      }
      
      tProgressBar = pb;
     }

  @Override
  protected Void doInBackground(URL... urls) {

   if (urls.length > 0){
    for(int i = 0; i < urls.length; i++){
     URL networkUrl = urls[i];
     
     try {
      tBM[i] = BitmapFactory.decodeStream(
        networkUrl.openConnection().getInputStream());
     } catch (IOException e) {
      e.printStackTrace();
     }
     
     publishProgress(i);
     
     //insert dummy delay to simulate lone time operation
     try {
      Thread.sleep(500);
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
     
    }
   }
   return null;
  }

  @Override
  protected void onPostExecute(Void result) {
   Toast.makeText(getBaseContext(), "Finished", Toast.LENGTH_LONG).show();
  }

  @Override
  protected void onProgressUpdate(Integer... values) {

   if(values.length > 0){
    for(int i = 0; i < values.length; i++){
     tIV[values[i]].setImageBitmap(tBM[values[i]]);
     tProgressBar.setProgress(values[i]+1);
    }
   }
   
  }

    }

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    <ProgressBar
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:id="@+id/loadingprogress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="5"
        android:progress="0"/>
    <ImageView
        android:id="@+id/target0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ImageView
        android:id="@+id/target1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ImageView
        android:id="@+id/target2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ImageView
        android:id="@+id/target3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ImageView
        android:id="@+id/target4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>


Remark: Permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.

download filesDownload the files.

Friday, September 28, 2012

Load Bitmap from internet in background thread using AsyncTask

This exercise show how to load bitmap from internet.

Load Bitmap from internet in background thread using AsyncTask


To load bitmap from internet, we can call the method:
BitmapFactory.decodeStream(networkUrl.openConnection().getInputStream());

BUT we have to do it in background thread other than Main Thread (Refer to the post android.os.NetworkOnMainThreadException). That's why we implement AsyncTask here.

Main Code:
package com.example.androidcolor;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;

public class MainActivity extends Activity {
 
 ImageView targetImage;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        targetImage = (ImageView)findViewById(R.id.target);
        
        //Load bitmap from internet
        String onLineImage = "http://goo.gl/1VArP";
        URL onLineURL;
        
  try {
   onLineURL = new URL(onLineImage);
   new MyNetworkTask(targetImage).execute(onLineURL);
  } catch (MalformedURLException e) {
   e.printStackTrace();
  }
        
    }
    
    private class MyNetworkTask extends AsyncTask<URL, Void, Bitmap>{
     
     ImageView tIV;
     
     public MyNetworkTask(ImageView iv){
      tIV = iv;
     }

  @Override
  protected Bitmap doInBackground(URL... urls) {

   Bitmap networkBitmap = null;
   
   URL networkUrl = urls[0]; //Load the first element
   try {
    networkBitmap = BitmapFactory.decodeStream(
      networkUrl.openConnection().getInputStream());
   } catch (IOException e) {
    e.printStackTrace();
   }

   return networkBitmap;
  }

  @Override
  protected void onPostExecute(Bitmap result) {
   tIV.setImageBitmap(result);
  }

    }

}


layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    <ImageView
        android:id="@+id/target"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>


Remark: Permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.

download filesDownload the files.

Next:
- execute AsyncTask with series of parameters to load image(s) from internet


Convert a Drawable to bitmap

It's a example to convert a local drawable to bitmap, then display on ImageView.

Convert a Drawable to bitmap


package com.example.androidcolor;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;

public class MainActivity extends Activity {
 
 ImageView targetImage;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        targetImage = (ImageView)findViewById(R.id.target);
        
        //Load bitmap locally in APK
        Bitmap srcBitmapLocal = BitmapFactory.decodeResource(
          getApplicationContext().getResources(),
          R.drawable.ic_launcher);
        targetImage.setImageBitmap(srcBitmapLocal);
        
    }

}


Thursday, September 27, 2012

Convert ImageView to black and white image using ColorFilter

The exercise "Example to apply ColorFilter on ImageView" demonstrate the basic operation of ColorFilter. By apply a suitable ColorMatrix, it's easy to convert a color image to black and white.

Convert ImageView to black and white image using ColorFilter

It's assumed that all red, green and blue have the same level, and equal to the average of the original red, green and blue. And user can adjust the brightness by varying the fifth element of each color in the ColorMatrix.

package com.example.androidcolorfilter;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.PorterDuff;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {
 
 ImageView imageView;
 SeekBar brightnessBar;
 TextView brightnessInfo;
 
 PorterDuff.Mode[] optMode = PorterDuff.Mode.values();
 
 String[] optModeName;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        imageView = (ImageView)findViewById(R.id.iv);
        brightnessBar = (SeekBar)findViewById(R.id.bar_brightness);
        brightnessInfo = (TextView)findViewById(R.id.brightness_info);

        brightnessBar.setOnSeekBarChangeListener(brightnessBarChangeListener);

        setBlackAndWhite(imageView);
        
        
    }
    
    OnSeekBarChangeListener brightnessBarChangeListener
    = new OnSeekBarChangeListener(){

  @Override
  public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
   setBlackAndWhite(imageView);
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  } 
    };

    
    private void setBlackAndWhite(ImageView iv){

     float brightness = (float)(brightnessBar.getProgress() - 255);
     
     float[] colorMatrix = { 
             0.33f, 0.33f, 0.33f, 0, brightness, //red
             0.33f, 0.33f, 0.33f, 0, brightness, //green
             0.33f, 0.33f, 0.33f, 0, brightness, //blue
             0, 0, 0, 1, 0    //alpha    
           };
     
     ColorFilter colorFilter = new ColorMatrixColorFilter(colorMatrix);
        iv.setColorFilter(colorFilter);
        
        brightnessInfo.setText(String.valueOf(brightness));
    }

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:src="@drawable/ic_launcher"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Brightness"/>
    
    <SeekBar 
            android:id="@+id/bar_brightness"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="512"
            android:progress="255"/>
    
    <TextView
        android:id="@+id/brightness_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Brightness"/>

</LinearLayout>


download filesDownload the files.

Wednesday, September 26, 2012

Are You Smart Enough to Work at Google?

Are You Smart Enough to Work at Google?: Fiendish and Impossible Interview Questions from the World's Top Companies


You are shrunk to the height of a ten-pence piece and thrown in a blender. The blades start moving in 60 seconds. What do you do? If you want to work at Google, or any of the world's top employers, you'll need to have a convincing answer to this and countless other tricky puzzles. Are You Smart Enough to Work at Google? reveals the new extreme interview questions in the post-crash, hypercompetitive job-market and uncovers the extraordinary lengths the best companies will go to find the right staff. William Poundstone guides readers through the surprising solutions to over a hundred of the most challenging conundrums actually used in interviews, as well as covering the importance of creative thinking, what your Facebook page says about you, and much more.

Tuesday, September 25, 2012

Life cycle of Fragments in ViewPager

In the exercise "Communication between Fragments in ViewPager" demonstrate how to pass data from Fragment A to Fragment B in a ViewPager. It's assumed that Fragment B is created when data is passed, and keep alive.

It's a case that the target Fragment haven't been created when data is passed, java.lang.NullPointerException will be thrown. And also another case the target Fragment have been destroyed after data passed.

So it's modified to keep buffer (saveToB and saveToC) in main activity (AndroidViewPagerActivity.java) to hold the data passed. In Fragment B and C, check any data exist in onResume() call-back method.

Life cycle of Fragments in ViewPager


fragment_a.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >
   <TextView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="It's Fragment A" />
   <EditText
       android:id="@+id/a_input"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" />
   <Button
       android:id="@+id/a_enter"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" 
       android:text="Enter to Fragment B"/>
   <Button
       android:id="@+id/a_enter_toC"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" 
       android:text="Enter to Fragment C"/>
</LinearLayout>


MyFragmentA.java
package com.exercise.AndroidViewPager;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MyFragmentA extends Fragment {
 
 EditText A_input;
 Button A_enter;
 Button A_enter_toC;

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);
  
  A_input = (EditText)myFragmentView.findViewById(R.id.a_input);
  A_enter = (Button)myFragmentView.findViewById(R.id.a_enter);
  A_enter.setOnClickListener(A_enterOnClickListener);
  A_enter_toC = (Button)myFragmentView.findViewById(R.id.a_enter_toC);
  A_enter_toC.setOnClickListener(AtoC_enterOnClickListener);
  
  return myFragmentView;
 }
 
 OnClickListener A_enterOnClickListener
 = new OnClickListener(){

  @Override
  public void onClick(View arg0) {
   
   String textPassToB = A_input.getText().toString();
   
   String TabOfFragmentB = ((AndroidViewPagerActivity)getActivity()).getTabFragmentB();
   
   MyFragmentB fragmentB = (MyFragmentB)getActivity()
     .getSupportFragmentManager()
     .findFragmentByTag(TabOfFragmentB);

   if(fragmentB == null){
    ((AndroidViewPagerActivity)getActivity()).putSaveToB(textPassToB);
    Toast.makeText(getActivity(), 
      "fragmentB == null", 
      Toast.LENGTH_LONG).show();
   }else{
    ((AndroidViewPagerActivity)getActivity()).putSaveToB(textPassToB);
    
    fragmentB.b_updateText(textPassToB);
    Toast.makeText(getActivity(), 
      "text sent to Fragment B:\n " + TabOfFragmentB, 
      Toast.LENGTH_LONG).show();
   }
   
   
  }};
  
  OnClickListener AtoC_enterOnClickListener
  = new OnClickListener(){

   @Override
   public void onClick(View arg0) {
    
    String textPassToC = A_input.getText().toString();
    
    String TabOfFragmentC = ((AndroidViewPagerActivity)getActivity()).getTabFragmentC();
    
    MyFragmentC fragmentC = (MyFragmentC)getActivity()
      .getSupportFragmentManager()
      .findFragmentByTag(TabOfFragmentC);
    
    if(fragmentC == null){
     ((AndroidViewPagerActivity)getActivity()).putSaveToC(textPassToC);
     Toast.makeText(getActivity(), 
       "fragmentC == null", 
       Toast.LENGTH_LONG).show();
    }else{
     ((AndroidViewPagerActivity)getActivity()).putSaveToC(textPassToC);
     
     fragmentC.c_updateText(textPassToC);
     Toast.makeText(getActivity(), 
       "text sent to Fragment C:\n " + TabOfFragmentC, 
       Toast.LENGTH_LONG).show();
    }

    
   }};

}


fragment_b.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >
   <TextView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="It's Fragment B" />
   <TextView
       android:id="@+id/b_received"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" />
   <ImageView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:scaleType="center"
       android:src="@drawable/ic_launcher"/>
</LinearLayout>


MyFragmentB.java
package com.exercise.AndroidViewPager;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

public class MyFragmentB extends Fragment {

 TextView b_received;
 
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  View myFragmentView = inflater.inflate(R.layout.fragment_b, container, false);
  
  b_received = (TextView)myFragmentView.findViewById(R.id.b_received);
  String myTag = getTag();
  
  ((AndroidViewPagerActivity)getActivity()).setTabFragmentB(myTag);
  
  Toast.makeText(getActivity(), 
    "MyFragmentB.onCreateView(): " + myTag, 
    Toast.LENGTH_LONG).show();

  return myFragmentView;
 }
 
 public void b_updateText(String t){
  b_received.setText(t);
 }

 @Override
 public void onResume() {
  super.onResume();
  String t = ((AndroidViewPagerActivity)getActivity()).getSaveToB();
  if(t != null){
   b_received.setText(t);
  }
  
  Toast.makeText(getActivity(), 
    "MyFragmentB.onResume()",
    Toast.LENGTH_LONG).show();
 }
 
 @Override
 public void onDestroyView() {
  super.onDestroyView();
  Toast.makeText(getActivity(), 
    "MyFragmentB.onDestroyView()",
    Toast.LENGTH_LONG).show();
 }

}


fragment_c.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >
   <TextView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="It's Fragment C" />
   <TextView
       android:id="@+id/c_received"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" />
</LinearLayout>


MyFragmentC.java
package com.exercise.AndroidViewPager;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

public class MyFragmentC extends Fragment {
 
 TextView c_received;

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  View myFragmentView = inflater.inflate(R.layout.fragment_c, container, false);
  
  c_received = (TextView)myFragmentView.findViewById(R.id.c_received);
  String myTag = getTag();
  
  ((AndroidViewPagerActivity)getActivity()).setTabFragmentC(myTag);
  
  Toast.makeText(getActivity(), 
    "MyFragmentC.onCreateView(): " + myTag, 
    Toast.LENGTH_LONG).show();
  
  return myFragmentView;
 }
 
 public void c_updateText(String t){
  c_received.setText(t);
 }
 
 @Override
 public void onResume() {
  super.onResume();
  String t = ((AndroidViewPagerActivity)getActivity()).getSaveToC();
  if(t != null){
   c_received.setText(t);
  }
  
  Toast.makeText(getActivity(), 
    "MyFragmentC.onResume()",
    Toast.LENGTH_LONG).show();
 }

 @Override
 public void onDestroyView() {
  super.onDestroyView();
  Toast.makeText(getActivity(), 
    "MyFragmentC.onDestroyView()",
    Toast.LENGTH_LONG).show();
 }

}


main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

</LinearLayout>


AndroidViewPagerActivity.java
package com.exercise.AndroidViewPager;

import java.util.ArrayList;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;

public class AndroidViewPagerActivity extends FragmentActivity {
 
 ViewPager mViewPager;
 TabsAdapter mTabsAdapter;
 
 String TabFragmentB;
 String TabFragmentC;
 
 String saveToB = null;
 String saveToC = null;
 
 public void setTabFragmentB(String t){
  TabFragmentB = t;
 }
 
 public String getTabFragmentB(){
  return TabFragmentB;
 }
 
 public void setTabFragmentC(String t){
  TabFragmentC = t;
 }
 
 public String getTabFragmentC(){
  return TabFragmentC;
 }
 
 public void putSaveToB(String textToSave){
  saveToB = textToSave;
 }
 
 public void putSaveToC(String textToSave){
  saveToC = textToSave;
 }
 
 public String getSaveToB(){
  String t = saveToB;
  return t;
 }
 
 public String getSaveToC(){
  String t = saveToC;
  return t;
 }
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        mViewPager = new ViewPager(this);
        mViewPager.setId(R.id.pager);
        setContentView(mViewPager);
        
        final ActionBar bar = getActionBar();
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);

        mTabsAdapter = new TabsAdapter(this, mViewPager);
        mTabsAdapter.addTab(bar.newTab().setText("Fragment A"),
                MyFragmentA.class, null);
        mTabsAdapter.addTab(bar.newTab().setText("Fragment B"),
          MyFragmentB.class, null);
        mTabsAdapter.addTab(bar.newTab().setText("Fragment C"),
          MyFragmentC.class, null);
        
        if (savedInstanceState != null) {
            bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
        }

    }

 @Override
 protected void onSaveInstanceState(Bundle outState) {
  //super.onSaveInstanceState(outState);
  outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
 }
 
 public static class TabsAdapter extends FragmentPagerAdapter
  implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
  
  private final Context mContext;
        private final ActionBar mActionBar;
        private final ViewPager mViewPager;
        private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
        
        static final class TabInfo {
            private final Class<?> clss;
            private final Bundle args;

            TabInfo(Class<?> _class, Bundle _args) {
                clss = _class;
                args = _args;
            }
        }

  public TabsAdapter(FragmentActivity activity, ViewPager pager) {
   super(activity.getSupportFragmentManager());
            mContext = activity;
            mActionBar = activity.getActionBar();
            mViewPager = pager;
            mViewPager.setAdapter(this);
            mViewPager.setOnPageChangeListener(this);
        }

  public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
            TabInfo info = new TabInfo(clss, args);
            tab.setTag(info);
            tab.setTabListener(this);
            mTabs.add(info);
            mActionBar.addTab(tab);
            notifyDataSetChanged();
        }

  @Override
  public void onPageScrollStateChanged(int state) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onPageSelected(int position) {
   // TODO Auto-generated method stub
   mActionBar.setSelectedNavigationItem(position);
  }

  @Override
  public void onTabReselected(Tab tab, FragmentTransaction ft) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onTabSelected(Tab tab, FragmentTransaction ft) {
   Object tag = tab.getTag();
            for (int i=0; i<mTabs.size(); i++) {
                if (mTabs.get(i) == tag) {
                    mViewPager.setCurrentItem(i);
                }
            }
  }

  @Override
  public void onTabUnselected(Tab tab, FragmentTransaction ft) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public Fragment getItem(int position) {
   TabInfo info = mTabs.get(position);
            return Fragment.instantiate(mContext, info.clss.getName(), info.args);
  }

  @Override
  public int getCount() {
   return mTabs.size();
  }

 }

}


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.exercise.AndroidViewPager"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="11" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AndroidViewPagerActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


download filesDownload the files.


Monday, September 24, 2012

PorterDuffColorFilter demonstration

It's a exercise to demonstrate the effects of various PorterDuff.Mode. You can try it interactively.

PorterDuffColorFilter demonstration


package com.example.androidcolorfilter;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import android.widget.TextView;

public class MainActivity extends Activity {
 
 ImageView imageView;

 SeekBar alphaBar, redBar, greenBar, blueBar;
 Spinner modeSpinner;
 TextView colorInfo;
 
 PorterDuff.Mode[] optMode = PorterDuff.Mode.values();
 
 String[] optModeName;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        imageView = (ImageView)findViewById(R.id.iv);
        
        alphaBar = (SeekBar)findViewById(R.id.bar_a);
        redBar = (SeekBar)findViewById(R.id.bar_r);
        greenBar = (SeekBar)findViewById(R.id.bar_g);
        blueBar = (SeekBar)findViewById(R.id.bar_b);
        
        colorInfo = (TextView)findViewById(R.id.colorinfo);

        alphaBar.setOnSeekBarChangeListener(colorBarChangeListener);
        redBar.setOnSeekBarChangeListener(colorBarChangeListener);
        greenBar.setOnSeekBarChangeListener(colorBarChangeListener);
        blueBar.setOnSeekBarChangeListener(colorBarChangeListener);
        
        modeSpinner = (Spinner)findViewById(R.id.mode);
        prepareOptModeName();
        ArrayAdapter<String> modeArrayAdapter = new ArrayAdapter<String>(
                this, 
                android.R.layout.simple_spinner_item, 
                optModeName);
        modeArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item );
        modeSpinner.setAdapter(modeArrayAdapter);
        modeSpinner.setSelection(0);
        modeSpinner.setOnItemSelectedListener(onModeItemSelectedListener);

        setPorterDuffColorFilter(imageView);
        
        
    }
    
    private void prepareOptModeName(){
     optModeName = new String[optMode.length];
     
     for(int i = 0; i < optMode.length; i++){
      optModeName[i] = optMode[i].toString();
     }
    }
    
    OnSeekBarChangeListener colorBarChangeListener
    = new OnSeekBarChangeListener(){

  @Override
  public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
   setPorterDuffColorFilter(imageView);
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  } 
    };
    
    OnItemSelectedListener onModeItemSelectedListener
    = new OnItemSelectedListener(){

  @Override
  public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
    long arg3) {
   setPorterDuffColorFilter(imageView);
   
  }

  @Override
  public void onNothingSelected(AdapterView<?> arg0) {
   // TODO Auto-generated method stub
   
  }
     
    };
    
    private void setPorterDuffColorFilter(ImageView iv){
     
     int srcColor = Color.argb(
       alphaBar.getProgress(), 
       redBar.getProgress(), 
       greenBar.getProgress(), 
       blueBar.getProgress());
     
     PorterDuff.Mode mode = optMode[modeSpinner.getSelectedItemPosition()];
     
     PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(srcColor, mode);
     iv.setColorFilter(porterDuffColorFilter);
     
     colorInfo.setText(
       "srcColor = #" + Integer.toHexString(srcColor) +"\n" +
       "mode = " + String.valueOf(mode.toString()) + " of total " + String.valueOf(optMode.length) + " modes.");
  
    }

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:src="@drawable/ic_launcher"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="srcColor"
        android:layout_alignParentLeft="true"/>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_a"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="a"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/bar_a"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_a"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_r"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="r"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/bar_r"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_r"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_g"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="g"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/bar_g"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_g"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_b"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="b"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/bar_b"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_b"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    <Spinner
        android:id="@+id/mode"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    
    <TextView
        android:id="@+id/colorinfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>


download filesDownload the files.

Saturday, September 22, 2012

Adjust lightness and darkness of ImageView, using LightingColorFilter.

Using LightingColorFilter, we can adjust lightness and darkness of ImageView by adjusting the passed parameter mul and add.

Adjust lightness and darkness of ImageView, using LightingColorFilter.


package com.example.androidcolorfilter;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.LightingColorFilter;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {
 
 ImageView imageView;

 SeekBar alphaMulBar, redMulBar, greenMulBar, blueMulBar;
 SeekBar alphaAddBar, redAddBar, greenAddBar, blueAddBar;
 TextView colorInfo;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        imageView = (ImageView)findViewById(R.id.iv);
        
        alphaMulBar = (SeekBar)findViewById(R.id.mula);
        redMulBar = (SeekBar)findViewById(R.id.mulr);
        greenMulBar = (SeekBar)findViewById(R.id.mulg);
        blueMulBar = (SeekBar)findViewById(R.id.mulb);
        
        alphaAddBar = (SeekBar)findViewById(R.id.adda);
        redAddBar = (SeekBar)findViewById(R.id.addr);
        greenAddBar = (SeekBar)findViewById(R.id.addg);
        blueAddBar = (SeekBar)findViewById(R.id.addb);
        
        colorInfo = (TextView)findViewById(R.id.colorinfo);

        alphaMulBar.setOnSeekBarChangeListener(colorBarChangeListener);
        redMulBar.setOnSeekBarChangeListener(colorBarChangeListener);
        greenMulBar.setOnSeekBarChangeListener(colorBarChangeListener);
        blueMulBar.setOnSeekBarChangeListener(colorBarChangeListener);
        
        alphaAddBar.setOnSeekBarChangeListener(colorBarChangeListener);
        redAddBar.setOnSeekBarChangeListener(colorBarChangeListener);
        greenAddBar.setOnSeekBarChangeListener(colorBarChangeListener);
        blueAddBar.setOnSeekBarChangeListener(colorBarChangeListener);

        setLightingColorFilter(imageView);
    }
    
    OnSeekBarChangeListener colorBarChangeListener
    = new OnSeekBarChangeListener(){

  @Override
  public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
   setLightingColorFilter(imageView);
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  } 
    };
    
    private void setLightingColorFilter(ImageView iv){
     
     int mul = Color.argb(
       alphaMulBar.getProgress(), 
       redMulBar.getProgress(), 
       greenMulBar.getProgress(), 
       blueMulBar.getProgress());
     
     int add = Color.argb(
       alphaAddBar.getProgress(), 
       redAddBar.getProgress(), 
       greenAddBar.getProgress(), 
       blueAddBar.getProgress());
     
     LightingColorFilter lightingColorFilter = new LightingColorFilter(mul, add);
     iv.setColorFilter(lightingColorFilter);
     
     colorInfo.setText(
       "mul = #" + Integer.toHexString(mul) +"\n" +
       "add = #" + Integer.toHexString(add));
     
    }

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:src="@drawable/ic_launcher"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="mul"
        android:layout_alignParentLeft="true"/>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_mul_a"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="a"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/mula"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_mul_a"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_mul_r"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="r"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/mulr"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_mul_r"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_mul_g"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="g"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/mulg"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_mul_g"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_mul_b"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="b"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/mulb"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_mul_b"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="add"
        android:layout_alignParentLeft="true"/>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_add_a"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="a"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/adda"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_add_a"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_add_r"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="r"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/addr"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_add_r"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_add_g"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="g"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/addg"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_add_g"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/text_add_b"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="b"
            android:layout_alignParentLeft="true"/>
        <SeekBar 
            android:id="@+id/addb"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/text_add_b"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>

    <TextView
        android:id="@+id/colorinfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>


download filesDownload the files.

Thursday, September 20, 2012

Swap color using ColorFilter

Last exercise demonstrate "how to apply ColorFilter on ImageView". Using ColorFilter, we can also change color components.

Swap color using ColorFilter


package com.example.androidcolorfilter;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrixColorFilter;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import android.widget.TextView;

public class MainActivity extends Activity {
 
 ImageView imageView;
 SeekBar Bar1, Bar2, Bar3;
 Spinner redSpinner, greenSpinner, blueSpinner;
 TextView colorInfo;
 
 String[] optColor  = { "Red", "Green", "Blue"};

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        imageView = (ImageView)findViewById(R.id.iv);
        
        Bar1 = (SeekBar)findViewById(R.id.bar1);
        Bar2 = (SeekBar)findViewById(R.id.bar2);
        Bar3 = (SeekBar)findViewById(R.id.bar3);
        
        redSpinner = (Spinner)findViewById(R.id.ropt);
        greenSpinner = (Spinner)findViewById(R.id.gopt);
        blueSpinner = (Spinner)findViewById(R.id.bopt);
        
        colorInfo = (TextView)findViewById(R.id.colorinfo);
        
        ArrayAdapter<String> redArrayAdapter = new ArrayAdapter<String>(
                this, 
                android.R.layout.simple_spinner_item, 
                optColor);
        redArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item );
        redSpinner.setAdapter(redArrayAdapter);
        redSpinner.setSelection(0);
        
        ArrayAdapter<String> greenArrayAdapter = new ArrayAdapter<String>(
                this, 
                android.R.layout.simple_spinner_item, 
                optColor);
        greenArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item );
        greenSpinner.setAdapter(greenArrayAdapter);
        greenSpinner.setSelection(1);
        
        ArrayAdapter<String> blueArrayAdapter = new ArrayAdapter<String>(
                this, 
                android.R.layout.simple_spinner_item, 
                optColor);
        blueArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item );
        blueSpinner.setAdapter(blueArrayAdapter);
        blueSpinner.setSelection(2);
        
        Bar1.setOnSeekBarChangeListener(colorBarChangeListener);
        Bar2.setOnSeekBarChangeListener(colorBarChangeListener);
        Bar3.setOnSeekBarChangeListener(colorBarChangeListener);
        
        redSpinner.setOnItemSelectedListener(colorSpinnerSelectedListener);
        greenSpinner.setOnItemSelectedListener(colorSpinnerSelectedListener);
        blueSpinner.setOnItemSelectedListener(colorSpinnerSelectedListener);
        
        setColorFilter(imageView);
    }
    
    OnSeekBarChangeListener colorBarChangeListener
    = new OnSeekBarChangeListener(){

  @Override
  public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
   setColorFilter(imageView);
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  } 
    };
  
 OnItemSelectedListener colorSpinnerSelectedListener
 = new OnItemSelectedListener(){

  @Override
  public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
    long arg3) {
   setColorFilter(imageView);
   
  }

  @Override
  public void onNothingSelected(AdapterView<?> arg0) {
   // TODO Auto-generated method stub
   
  } 
 };
    
    private void setColorFilter(ImageView iv){
     
       /*
        * 5x4 matrix for transforming the color+alpha components of a Bitmap. 
        * The matrix is stored in a single array, and its treated as follows: 
        * [  a, b, c, d, e, 
        *   f, g, h, i, j, 
        *   k, l, m, n, o, 
        *   p, q, r, s, t ] 
        * 
        * When applied to a color [r, g, b, a], the resulting color is computed 
        * as (after clamping) 
        * R' = a*R + b*G + c*B + d*A + e; 
        * G' = f*R + g*G + h*B + i*A + j; 
        * B' = k*R + l*G + m*B + n*A + o; 
        * A' = p*R + q*G + r*B + s*A + t;
        */
     
     
     float value1 = ((float)Bar1.getProgress())/255;
     float value2 = ((float)Bar2.getProgress())/255;
     float value3 = ((float)Bar3.getProgress())/255;
     
     int redColorSource = redSpinner.getSelectedItemPosition();
     int greenColorSource = greenSpinner.getSelectedItemPosition();
     int blueColorSource = blueSpinner.getSelectedItemPosition();
     
     float a, b, c, f, g, h, k, l, m;
     a = b = c = f = g = h = k = l = m = 0;
     
     String colorCombination = "";
     
     colorCombination += "RED = ";
     switch(redColorSource){
     case 0: a = value1;
       colorCombination += "red x " + String.valueOf(value1) +"\n";
       break;
     case 1: b = value1;
       colorCombination += "green x " + String.valueOf(value1) +"\n";
    break;
     case 2: c = value1;
       colorCombination += "blue x " + String.valueOf(value1) +"\n";
    break;
     }
     
     colorCombination += "GREEN = ";
     switch(greenColorSource){
     case 0: f = value2;
       colorCombination += "red x " + String.valueOf(value2) +"\n";
       break;
     case 1: g = value2;
       colorCombination += "green x " + String.valueOf(value2) +"\n";
    break;
     case 2: h = value2;
       colorCombination += "blue x " + String.valueOf(value2) +"\n";
    break;
     }
     
     colorCombination += "BLUE = ";
     switch(blueColorSource){
     case 0: k = value3;
       colorCombination += "red x " + String.valueOf(value3) +"\n";
       break;
     case 1: l = value3;
       colorCombination += "green x " + String.valueOf(value3) +"\n";
    break;
     case 2: m = value3;
       colorCombination += "blue x " + String.valueOf(value3) +"\n";
    break;
     }
     
     float[] colorMatrix = { 
       a, b, c, 0, 0, //red
       f, g, h, 0, 0, //green
       k, l, m, 0, 0, //blue
       0, 0, 0, 1, 0  //alpha    
     };
     
     colorInfo.setText(colorCombination);
     
     ColorFilter colorFilter = new ColorMatrixColorFilter(colorMatrix);
     
     iv.setColorFilter(colorFilter);
    }

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:src="@drawable/ic_launcher"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Color"
                android:layout_alignParentLeft="true"/>
        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Source"
                android:layout_alignParentRight="true"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/rtext"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="R"
            android:layout_alignParentLeft="true"/>
        <Spinner
            android:id="@+id/ropt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"/>
        <SeekBar 
            android:id="@+id/bar1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/rtext"
            android:layout_toLeftOf="@id/ropt"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/gtext"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="G"
            android:layout_alignParentLeft="true"/>
        <Spinner
            android:id="@+id/gopt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"/>
        <SeekBar 
            android:id="@+id/bar2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/gtext"
            android:layout_toLeftOf="@id/gopt"/>
    </RelativeLayout>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/btext"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="B"
            android:layout_alignParentLeft="true"/>
        <Spinner
            android:id="@+id/bopt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"/>
        <SeekBar 
            android:id="@+id/bar3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="255"
            android:progress="255"
            android:layout_toRightOf="@id/btext"
            android:layout_toLeftOf="@id/bopt"/>
    </RelativeLayout>
    
    <TextView
        android:id="@+id/colorinfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>


download filesDownload the files.

Wednesday, September 19, 2012

Example to apply ColorFilter on ImageView

Example to apply ColorFilter on ImageView


package com.example.androidcolorfilter;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrixColorFilter;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

public class MainActivity extends Activity {
 
 ImageView imageView;
 SeekBar redBar, greenBar, blueBar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        imageView = (ImageView)findViewById(R.id.iv);
        redBar = (SeekBar)findViewById(R.id.redbar);
        greenBar = (SeekBar)findViewById(R.id.greenbar);
        blueBar = (SeekBar)findViewById(R.id.bluebar);
        
        redBar.setOnSeekBarChangeListener(colorBarChangeListener);
        greenBar.setOnSeekBarChangeListener(colorBarChangeListener);
        blueBar.setOnSeekBarChangeListener(colorBarChangeListener);
        
        setColorFilter(imageView);
    }
    
    OnSeekBarChangeListener colorBarChangeListener
    = new OnSeekBarChangeListener(){

  @Override
  public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
   setColorFilter(imageView);
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
   // TODO Auto-generated method stub
   
  }};
    
    private void setColorFilter(ImageView iv){
     
       /*
        * 5x4 matrix for transforming the color+alpha components of a Bitmap. 
        * The matrix is stored in a single array, and its treated as follows: 
        * [  a, b, c, d, e, 
        *   f, g, h, i, j, 
        *   k, l, m, n, o, 
        *   p, q, r, s, t ] 
        * 
        * When applied to a color [r, g, b, a], the resulting color is computed 
        * as (after clamping) 
        * R' = a*R + b*G + c*B + d*A + e; 
        * G' = f*R + g*G + h*B + i*A + j; 
        * B' = k*R + l*G + m*B + n*A + o; 
        * A' = p*R + q*G + r*B + s*A + t;
        */
     
     
     float redValue = ((float)redBar.getProgress())/255;
     float greenValue = ((float)greenBar.getProgress())/255;
     float blueValue = ((float)blueBar.getProgress())/255;
     
     float[] colorMatrix = { 
       redValue, 0, 0, 0, 0,  //red
       0, greenValue, 0, 0, 0, //green
       0, 0, blueValue, 0, 0,  //blue
       0, 0, 0, 1, 0    //alpha    
     };
     
     ColorFilter colorFilter = new ColorMatrixColorFilter(colorMatrix);
     
     iv.setColorFilter(colorFilter);

    }


}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:src="@drawable/ic_launcher"/>
    
    <SeekBar 
        android:id="@+id/redbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="255"/>
    <SeekBar 
        android:id="@+id/greenbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="255"/>
    <SeekBar 
        android:id="@+id/bluebar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="255"/>

</LinearLayout>


download filesDownload the files.

Next:
- Swap color using ColorFilter
- Convert color image to black and white using ColorFilter


Tuesday, September 18, 2012

Example of using PorterDuffColorFilter

android.graphics.PorterDuffColorFilter create a colorfilter that uses the specified color and porter-duff mode. The source color and porter-duff mode can be specified in the constructor, PorterDuffColorFilter (int srcColor, PorterDuff.Mode mode).

Example of using PorterDuffColorFilter


Modify onDraw() method of MyView.java in the post "Example of using ColorMatrixColorFilter".

 @Override
 protected void onDraw(Canvas canvas) {
  
  int srcColor= 0xFF00FF00;
  PorterDuff.Mode mode = PorterDuff.Mode.ADD;
  
  PorterDuffColorFilter porterDuffColorFilter 
   = new PorterDuffColorFilter(srcColor, mode);

  Paint MyPaint_Normal = new Paint();
  Paint MyPaint_PorterDuff = new Paint();
  MyPaint_PorterDuff.setColorFilter(porterDuffColorFilter);
     
     Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
     canvas.drawBitmap(myBitmap, 400, 100, MyPaint_Normal);
     canvas.drawBitmap(myBitmap, 500, 100, MyPaint_PorterDuff);
     
 };


download filesDownload the files.

Related:
- Interactive demonstration of PorterDuffColorFilter.


Friday, September 14, 2012

LightingColorFilter example

android.graphics.LightingColorFilter is a colorfilter that multiplies the RGB channels by one color, and then adds a second color, pinning the result for each component to [0..255].

LightingColorFilter example


Modify onDraw() method of MyView.java in the post "Example of using ColorMatrixColorFilter".
 @Override
 protected void onDraw(Canvas canvas) {
  
  int mul = 0xFFFFFF00; //remove BLUE component
  int add = 0x0000FF00; //set GREEN full
  LightingColorFilter lightingColorFilter = new LightingColorFilter(mul, add);
  
  Paint MyPaint_Normal = new Paint();
  Paint MyPaint_Lighting = new Paint();
  MyPaint_Lighting.setColorFilter(lightingColorFilter);
     
     Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
     canvas.drawBitmap(myBitmap, 400, 100, MyPaint_Normal);
     canvas.drawBitmap(myBitmap, 500, 100, MyPaint_Lighting);
     
 };


download filesDownload the files.

Related:
- Adjust lightness and darkness of ImageView, using LightingColorFilter.

Thursday, September 13, 2012

Google Play Android Developer now support multiple APK


Google Play Android Developer have added new functionality for apps that use multiple APK support. Developers can now target each APK to a specific native platform.

Multiple APK support is a feature on Google Play that allows you to publish different APKs for your application that are each targeted to different device configurations. Each APK is a complete and independent version of your application, but they share the same application listing on Google Play and must share the same package name and be signed with the same release key. This feature is useful for cases in which your application cannot reach all desired devices with a single APK.

Know more about Multiple APK Support: http://developer.android.com/guide/google/play/publishing/multiple-apks.html

Wednesday, September 12, 2012

Video Tutorial - Android Design in Action: Transit Apps

Android Design in Action: Transit Apps

Join Roman Nurik and Nick Butcher for a live show as they discuss various elements of Android Design in the context of apps reviewed during The Friday App Clinic.

Generate negative image using ColorMatrix

Last exercise demonstrate "how to use ColorMatrix to change Bitmap". With a suitable ColorMatrix assigned to ColorMatrixColorFilter(), we can generate negative image easily.

Generate negative image using ColorMatrix


Modify onDraw() method of MyView.java in last exercise.
 @Override
 protected void onDraw(Canvas canvas) {
  
  //To generate negative image
  float[] colorMatrix_Negative = { 
    -1.0f, 0, 0, 0, 255, //red
    0, -1.0f, 0, 0, 255, //green
    0, 0, -1.0f, 0, 255, //blue
    0, 0, 0, 1.0f, 0 //alpha  
  };
  
  Paint MyPaint_Normal = new Paint();
  Paint MyPaint_Negative = new Paint();
  ColorFilter colorFilter_Negative = new ColorMatrixColorFilter(colorMatrix_Negative);
  MyPaint_Negative.setColorFilter(colorFilter_Negative);
     
     Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
     canvas.drawBitmap(myBitmap, 400, 100, MyPaint_Normal);
     canvas.drawBitmap(myBitmap, 500, 100, MyPaint_Negative);
 };


download filesDownload the files.

Learn HTML5 and JavaScript for Android


Learn HTML5 and JavaScript for Android teaches the essential HTML5 and JavaScript skills you need to make great apps for the Android platform and browser.

This book guides you through the creation of a mobile web app. You'll put the HTML5, CSS3 and JavaScript skills you learn into practice, giving you invaluable first-hand experience that will serve you well as you go on to develop your own web apps for Android smartphones and tablets.

Throughout this book, you will learn new skills and bring these altogether to create a web app that runs on the Android platform as well as other mobile platforms.

What you’ll learn

Android 4.0 compliant, this book shows you how to: 
  • How to build a HTML5 and JavaScript-based mobile Web app that runs on Android devices and browsers
  • What is HTML5 and how to best use it for your presentation tier in your Web app
  • What is CSS3 and how to best employ it for a richer presentation tier in your Web app
  • What is JavaScript and how to best use for any needed logic in your web app
  • How to make use of some of the HTML API’s such as Canvas, Video and Audio for mobile to create a richer experience for users
  • How to build a Web app, case by case, tier by tier, for your Android devices and for your prospective audience

    Who this book is for

    This book is for Android and web developers needing to learn the mobile web skills needed to build reactive, dynamic and fun HTML5 and JavaScript-based Web Apps that run on Android devices and its browsers.

    Table of Contents

    1. Introduction and Shopping list
    2. Learn Your First Web App for Android
    3. Learn HTML5
    4. Create using HTML5 Workshop (Web app case study part I)
    5. Learn CSS3
    6. Create and Refine using CSS3 (Web app case study part II)
    7. Learn JavaScript
    8. Create using JavaScript (Web app case study part III)
    9. Testing and Deploying Your First Web App

    Tuesday, September 11, 2012

    Example of using ColorMatrixColorFilter

    More examples of drawing on canvas of custom View listed HERE.

    Example of using setColorFilter(ColorFilter) of Paint to apply color filter on bitmap.

    Example of using ColorMatrixColorFilter


    Create out custom View, MyView.java. Override onDraw(Canvas canvas) method to apply ColorFilter to Paint.

    package com.example.androiddraw;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.ColorFilter;
    import android.graphics.ColorMatrixColorFilter;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.view.View;
    
    public class MyView extends View {
     
     Paint BackPaint = new Paint();
     Context MyContext;
    
     public MyView(Context context) {
      super(context);
      init(context);
     }
    
     public MyView(Context context, AttributeSet attrs) {
      super(context, attrs);
      init(context);
     }
    
     public MyView(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
      init(context);
     }
     
     private void init(Context ctx){
      MyContext = ctx;
      BackPaint.setStyle(Paint.Style.FILL);
      BackPaint.setColor(Color.BLACK);
      
     }
    
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      int w = MeasureSpec.getSize(widthMeasureSpec);
      int h = MeasureSpec.getSize(heightMeasureSpec);
      setMeasuredDimension(w, h);
     }
    
     @Override
     protected void onDraw(Canvas canvas) {
      
      /*
       * 5x4 matrix for transforming the color+alpha components of a Bitmap. 
       * The matrix is stored in a single array, and its treated as follows: 
       * [  a, b, c, d, e, 
       *   f, g, h, i, j, 
       *   k, l, m, n, o, 
       *   p, q, r, s, t ] 
       * 
       * When applied to a color [r, g, b, a], the resulting color is computed 
       * as (after clamping) 
       * R' = a*R + b*G + c*B + d*A + e; 
       * G' = f*R + g*G + h*B + i*A + j; 
       * B' = k*R + l*G + m*B + n*A + o; 
       * A' = p*R + q*G + r*B + s*A + t;
       */
      
      // Identity Matrix
      /*
      float[] colorMatrix = { 
        1, 0, 0, 0, 0, //red
        0, 1, 0, 0, 0, //green
        0, 0, 1, 0, 0, //blue
        0, 0, 0, 1, 0 //alpha  
      };*/
      
      float[] colorMatrix = { 
        1, 0, 0, 0, 0, //red
        0, 0, 0, 0, 0, //green
        0, 0, 0, 0, 0, //blue
        0, 0, 0, 1, 0 //alpha  
      };
      
      Paint MyPaint = new Paint();
      ColorFilter colorFilter = new ColorMatrixColorFilter(colorMatrix);
         MyPaint.setColorFilter(colorFilter);
         
         Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
         canvas.drawBitmap(myBitmap, 100, 100, MyPaint);
     };
     
    }
    


    Modify the main activity, MainActivity.java, to set MyView as ContentView.
    package com.example.androiddraw;
    
    import android.os.Bundle;
    import android.app.Activity;
    
    public class MainActivity extends Activity {
    
     @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            
            MyView myView = new MyView(this);
            setContentView(myView);
        }
        
    }
    


    download filesDownload the files.

    Related:
    - Generate negative image using ColorMatrix
    - LightingColorFilter example
    - PorterDuffColorFilter example
    - Example to apply ColorFilter on ImageView

    Monday, September 10, 2012

    Firefox OS Demo

    Firefox OS Demo, run on a developer phone by ZTE.


    Example of RadialGradient

    Example of RadialGradient:

    RadialGradient


    Modify onDraw(Canvas canvas) method of MyView.java in the exercise of LinearGradient.

     @Override
     protected void onDraw(Canvas canvas) {
    
      float w, h, cx, cy, radius;
      w = getWidth();
      h = getHeight();
      cx = w/2;
      cy = h/2;
      
      if(w > h){
       radius = h/4; 
      }else{
       radius = w/4; 
      }
        
      canvas.drawRect(0, 0, w, h, BackPaint);
        
      Paint MyPaint = new Paint();
      MyPaint.setStyle(Paint.Style.FILL);
        
      float shaderCx = 0;
      float shaderCy = 0;
      float shaderRadius = w;
      int shaderColor0 = Color.WHITE;
      int shaderColor1 = Color.BLACK;
      MyPaint.setAntiAlias(true);
      Shader radialGradientShader;
      
      radialGradientShader = new RadialGradient(
        shaderCx, shaderCy, shaderRadius,
        shaderColor0, shaderColor1,
        Shader.TileMode.MIRROR);
        
      MyPaint.setShader(radialGradientShader);
      canvas.drawRect(0, 0, w, h, MyPaint);
        
      shaderCx = cx;
      shaderCy = cy;
      shaderRadius = radius;
      shaderColor0 = Color.RED;
      shaderColor1 = Color.BLUE;
      
      radialGradientShader = new RadialGradient(
        shaderCx, shaderCy, shaderRadius,
        shaderColor0, shaderColor1,
        Shader.TileMode.MIRROR);
        
      MyPaint.setShader(radialGradientShader);
      canvas.drawCircle(cx, cy, radius, MyPaint); 
     };
    


    download filesDownload the files.

    - More samples of drawing on canvas.

    Sunday, September 9, 2012

    Draw bitmap with shadow on canvas

    More examples of drawing on canvas of custom View listed HERE.

    Last exercise demonstrate how to "Draw text with shadow on canvas". It can be modify to display bitmap with canvas.

     @Override
     protected void onDraw(Canvas canvas) {
      
      float w, h, cx, cy;
      w = getWidth();
      h = getHeight();
      cx = w/2;
      cy = h/2;
    
      canvas.drawColor(Color.GRAY);
      
      Bitmap myBitmap = BitmapFactory.decodeResource(
        getResources(), 
        R.drawable.ic_launcher);
    
            Paint shadowPaint = new Paint();
            shadowPaint.setAntiAlias(true);
            shadowPaint.setColor(Color.WHITE);
            shadowPaint.setTextSize(45.0f);
            shadowPaint.setStrokeWidth(2.0f);
            shadowPaint.setStyle(Paint.Style.STROKE);
            shadowPaint.setShadowLayer(5.0f, 10.0f, 10.0f, Color.BLACK);
            
            canvas.drawText("http://android-er.blogspot.com/", 50, 200, shadowPaint);
            canvas.drawBitmap(myBitmap, cx, cy, shadowPaint);
      
     };
    


    Run on Nexus One, Android 2.3.6

    Draw bitmap with shadow on canvas, run on Nexus One, Android 2.3.6

    BUT, NO SHADOW displayed if run on HTC One X of Android 4.0.3!

    For API Level 11, you have to call setLayerType (int layerType, Paint paint) to specifies the type of layer backing the View.

     @Override
     protected void onDraw(Canvas canvas) {
      
      float w, h, cx, cy;
      w = getWidth();
      h = getHeight();
      cx = w/2;
      cy = h/2;
    
      canvas.drawColor(Color.GRAY);
      
      Bitmap myBitmap = BitmapFactory.decodeResource(
        getResources(), 
        R.drawable.ic_launcher);
    
            Paint shadowPaint = new Paint();
            shadowPaint.setAntiAlias(true);
            shadowPaint.setColor(Color.WHITE);
            shadowPaint.setTextSize(45.0f);
            shadowPaint.setStrokeWidth(2.0f);
            shadowPaint.setStyle(Paint.Style.STROKE);
            shadowPaint.setShadowLayer(5.0f, 10.0f, 10.0f, Color.BLACK);
            
            //for android:minSdkVersion="11"
            setLayerType(LAYER_TYPE_SOFTWARE, shadowPaint);
            
            canvas.drawText("http://android-er.blogspot.com/", 50, 200, shadowPaint);
            canvas.drawBitmap(myBitmap, cx, cy, shadowPaint);
      
     };
    

    Run on HTC One X, Android 4.0.3

    Draw bitmap with shadow on canvas, run on HTC One X, Android 4.0.3


    download filesDownload the files.

    Saturday, September 8, 2012

    Draw text with shadow on canvas

    More examples of drawing on canvas of custom View listed HERE.

    To draw text with shadow on canvas, Modify onDraw(Canvas canvas) method of MyView.java in the exercise.

     @Override
     protected void onDraw(Canvas canvas) {
    
      canvas.drawColor(Color.GRAY);
    
            Paint shadowPaint = new Paint();
            shadowPaint.setAntiAlias(true);
            shadowPaint.setColor(Color.WHITE);
            shadowPaint.setTextSize(45.0f);
            shadowPaint.setStrokeWidth(2.0f);
            shadowPaint.setStyle(Paint.Style.STROKE);
            shadowPaint.setShadowLayer(5.0f, 10.0f, 10.0f, Color.BLACK);
            
            canvas.drawText("http://android-er.blogspot.com/", 50, 200, shadowPaint);
      
     };
    


    Draw text with shadow on canvas


    download filesDownload the files.


    Friday, September 7, 2012

    File Explorer with sorting, in alphabetical and lastModified.

    I have a former exercise of "File Explorer", with Sorting in alphabetical order ignore case, and Sorting in lastModified time. Here, I will group them together to make buttons for user to select Sorting method.

    File Explorer with sorting


    Modify layout file to add buttons for sorting method.
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" 
        android:orientation="vertical">
        
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <Button
                android:id="@+id/button_alphabetically"
                android:layout_width="0dp" 
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="alphabetically"/>
            <Button
                android:id="@+id/button_lastDateModified"
                android:layout_width="0dp" 
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="lastDateModified"/>
        </LinearLayout>
        <TextView
            android:id="@+id/path"
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" />
        
        <ListView
            android:id="@android:id/list"
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            />
        <TextView
            android:id="@android:id/empty"
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            android:text="No Data"
            />
    
    </LinearLayout>
    


    Main code:
    package com.example.androidexplorer;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.List;
    
    import android.os.Bundle;
    import android.os.Environment;
    import android.app.AlertDialog;
    import android.app.ListActivity;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.ArrayAdapter;
    import android.widget.Button;
    import android.widget.ListView;
    import android.widget.TextView;
    
    public class MainActivity extends ListActivity {
     
     private List<String> item = null;
     private List<String> path = null;
     private String root;
     private TextView myPath;
     
     private String currentPath;
     Comparator<? super File> comparator;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            myPath = (TextView)findViewById(R.id.path);
            
            comparator = filecomparatorByAlphabetically;
            root = Environment.getExternalStorageDirectory().getPath();
            getDir(root);
            
            Button btnAlphabetically = (Button)findViewById(R.id.button_alphabetically);
            btnAlphabetically.setOnClickListener(new OnClickListener(){
    
       @Override
       public void onClick(View arg0) {
        comparator = filecomparatorByAlphabetically;
        getDir(currentPath);
        
       }});
            
            Button btnLastDateModified = (Button)findViewById(R.id.button_lastDateModified);
            btnLastDateModified.setOnClickListener(new OnClickListener(){
    
       @Override
       public void onClick(View arg0) {
        comparator = filecomparatorByLastModified;
              getDir(currentPath);
        
       }});
        }
        
        private void getDir(String dirPath)
        {
         currentPath = dirPath;
         
         myPath.setText("Location: " + dirPath);
         item = new ArrayList<String>();
         path = new ArrayList<String>();
         File f = new File(dirPath);
         File[] files = f.listFiles();
         
         if(!dirPath.equals(root))
         {
          item.add(root);
          path.add(root);
          item.add("../");
          path.add(f.getParent()); 
         }
         
         Arrays.sort(files, comparator);
         
         for(int i=0; i < files.length; i++)
         {
          File file = files[i];
          
          if(!file.isHidden() && file.canRead()){
           path.add(file.getPath());
              if(file.isDirectory()){
               item.add(file.getName() + "/");
              }else{
               item.add(file.getName());
              }
          } 
         }
    
         ArrayAdapter<String> fileList =
           new ArrayAdapter<String>(this, R.layout.row, item);
         setListAdapter(fileList); 
        }
        
        Comparator<? super File> filecomparatorByLastModified = new Comparator<File>(){
      
      public int compare(File file1, File file2) {
    
       if(file1.isDirectory()){
        if (file2.isDirectory()){
         return Long.valueOf(file1.lastModified()).compareTo(file2.lastModified());
        }else{
         return -1;
        }
       }else {
        if (file2.isDirectory()){
         return 1;
        }else{
         return Long.valueOf(file1.lastModified()).compareTo(file2.lastModified());
        }
       }
        
      }  
     };
        
        Comparator<? super File> filecomparatorByAlphabetically = new Comparator<File>(){
      
      public int compare(File file1, File file2) {
    
       if(file1.isDirectory()){
        if (file2.isDirectory()){
         return String.valueOf(file1.getName().toLowerCase()).compareTo(file2.getName().toLowerCase());
        }else{
         return -1;
        }
       }else {
        if (file2.isDirectory()){
         return 1;
        }else{
         return String.valueOf(file1.getName().toLowerCase()).compareTo(file2.getName().toLowerCase());
        }
       }
        
      }  
     };
     
     @Override
     protected void onListItemClick(ListView l, View v, int position, long id) {
      // TODO Auto-generated method stub
      File file = new File(path.get(position));
      
      if (file.isDirectory())
      {
       if(file.canRead()){
        getDir(path.get(position));
       }else{
        new AlertDialog.Builder(this)
         .setIcon(R.drawable.ic_launcher)
         .setTitle("[" + file.getName() + "] folder can't be read!")
         .setPositiveButton("OK", null).show(); 
       } 
      }else {
       new AlertDialog.Builder(this)
         .setIcon(R.drawable.ic_launcher)
         .setTitle("[" + file.getName() + "]")
         .setPositiveButton("OK", null).show();
    
        }
     }
    
    }
    


    /res/layout/row.xml, the layout of the rows in the list.
    <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/rowtext"
        android:layout_width="fill_parent"
        android:layout_height="30sp"
        android:textSize="25sp" />
    


    Please notice that if you target for minimum SDK of level 16, Android 4.1, you have to add permission of READ_EXTERNAL_STORAGE in AndroidManifest.xml.

    download filesDownload the files.

    Related:
    - File Explorer, access SD Card on Samsung Galaxy S3