Monday 6 February 2017

Remove extra spaces from an image

Remove extra spaces from an image 


I required an image with no side spaces as I had one with. So after going througha lot of help over the internet i could find a portion removal code. And now finally I have my code for the all four side spaces removal.
Here we go :


public static Bitmap TrimBitmap(Bitmap bmp) {
    int imgHeight = bmp.getHeight();
    int imgWidth  = bmp.getWidth();


    //TRIM WIDTH - LEFT
    int startWidth = 0;
    for(int x = 0; x < imgWidth; x++) {
        if (startWidth == 0) {
            for (int y = 0; y < imgHeight; y++) {
                if (bmp.getPixel(x, y) != Color.TRANSPARENT) {
                    startWidth = x;
                    break;
                }
            }
        } else break;
    }


    //TRIM WIDTH - RIGHT
    int endWidth  = 0;
    for(int x = imgWidth - 1; x >= 0; x--) {
        if (endWidth == 0) {
            for (int y = 0; y < imgHeight; y++) {
                if (bmp.getPixel(x, y) != Color.TRANSPARENT) {
                    endWidth = x;
                    break;
                }
            }
        } else break;
    }



    //TRIM HEIGHT - TOP
    int startHeight = 0;
    for(int y = 0; y < imgHeight; y++) {
        if (startHeight == 0) {
            for (int x = 0; x < imgWidth; x++) {
                if (bmp.getPixel(x, y) != Color.TRANSPARENT) {
                    startHeight = y;
                    break;
                }
            }
        } else break;
    }



    //TRIM HEIGHT - BOTTOM
    int endHeight = 0;
    for(int y = imgHeight - 1; y >= 0; y--) {
        if (endHeight == 0 ) {
            for (int x = 0; x < imgWidth; x++) {
                if (bmp.getPixel(x, y) != Color.TRANSPARENT) {
                    endHeight = y;
                    break;
                }
            }
        } else break;
    }


    return Bitmap.createBitmap(
            bmp,
            startWidth,
            startHeight,
            endWidth - startWidth,
            endHeight - startHeight
    );

}


Explanation: For each side of the image, a FOR loop is run to check if pixels does not contains transparent color, returning the first non-transparent pixel useful coordinate. This is done elaborating coordinates using as a base the opposite dimension than the dimension to trim: to find y, scan x for every y.
To check where the Vertical-Top blank space ends, it runs the following steps:
1. Starting is from the top row (y=0)
2. Checks all the columns of the row (x from 0 to imageWidth)
3. If a non-transparent pixel is found, break the loop and save the y coordinate. Otherwise continue.
4. At the ending of the columns, go to the next row (y+1) and start checking columns agains. Break if a non-transparent pixel has already been found.

Similiar methods are used for the other dimensions, only changing the direction of the scan.
Once obtained the 4 coordinates for the first useful pixels of the image, the Bitmap.createBitmapmethod is invoked, with the original bitmap as a base image, and the useful pixels coordinates as Top-Left and Bottom-Right limits for the resize.


Note 1: It is useful to note that the coordinates 0, 0 equals to Top-Left.
Note 2: The ending width and height in Bitmap.createBitmap are reduced by the new starting relative coordinate, otherwise the new image will have the boundaries wrongly pushed bottom-right. Figure it like this: you have an image 100x100px, so with ending coordinates 100,100. Changing the starting coordinates to 50,50 will bring the ending coordinates of your elaboration rectangle to 150,150 (100 original coordinate + 50 of modified starting point), pushing it outside the original image boundaries. To avoid this, the new ending coordinate is reduced by the new starting coordinate (100 + 50 new starting coord - 50 new starting coord adjustment)
Note 3: in the original answer, a check for all the pixels in a given direction is run using the same dimension of the coordinate to find, returning the most advanced useful pixel. Checking the opposite dimension and stopping at the first useful pixel increased performances.

Sunday 5 February 2017

Multiple dialogs creation in Android

Multiple dialogs creation in Android is a common problem .Let's seek solution to it

Today we will discuss on how to avoid creation of multiple dialog from the same piece of code.

The key is to maintain a counter and if its 0 , that means no dialog is showing now then only show a dialog. And on every dismissal of the dialog we reduce that counter to maintain the count of the dialog shown . That means at one time it should be not more than one .
 
   //the counter to maintain the showing status of the dialog
   private static int dialog_count =0;
    private Dialog dialog=null;
   
    public void showAlertDialog(final Context context, Activity activity) {

        ListAdapter arrayAdapter;
        final ArrayList<Language> arraylist = new ArrayList<>();
        Integer[] imageId = {
                R.drawable.british_english_flag,
                R.drawable.swedish_flag_small,
                R.drawable.italian_flag
        };

        final String[] languages = context.getResources().getStringArray(R.array.language_list);
        for (int i = 0; i < languages.length; i++) {
            Language langObj = new Language(languages[i].substring(3, languages[i].length()), imageId[i]);
            arraylist.add(langObj);
        }
        arrayAdapter = new LanguageArrayAdpater(activity, arraylist);

        dialog = new Dialog(mContext);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);

     
        View view = mActivity.getLayoutInflater().inflate(R.layout.dialog_layout, null);

        ListView lv = (ListView) view.findViewById(R.id.listView_language);
        TextView tv_header = (TextView) view.findViewById(R.id.dialog_header);
        tv_header.setTypeface(Utility.setTypeFace(Defines.font_OpenSansRegular));

        lv.setAdapter(arrayAdapter);

        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String selectedVal = arraylist.get(position).getName();
                Log.d(TAG, "chosen " + selectedVal);
                dialog.dismiss();
//if an item is selected and the dialog was showing then reduce the dialog counter and perform the required action
                if(dialog_count>0)
                    dialog_count--;
                saveInPrefs(languages,context, position, selectedVal);
            }
        });

        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {
                System.out.println("dialog count dismissing :"+ dialog_count);
//if the dialog was cancelable then on dismissing it we reduce the count so that we have proper data in the counter
                if(dialog_count>0)
                    dialog_count--;
                System.out.println("dialog count dismissed :"+ dialog_count);
            }
        });
        dialog.setContentView(view);
//show the dialog only if we have no dialog showing currently.
        if(dialog_count==0) {
            dialog.show();
            dialog_count++;
        }

To show dialog from outside the activity Android

To show dialog from outside the activity



Suppose you have a requirement to show the dialog from outside the activity or to show dialog from more than one activity or fragment .
So the efficient solution to it is to show it from a common method in some file .For this an approach that I found is to just implement the function call to show the dialog in a common file and make a call to it from all of your required places.


This looks good . But what if on the basis of the response “YES”, or “NO”, selected by the user requires you to perform some functionality on the calling class view ,like calling an api or updating the activity views. Then we will required to implement a callback for the selected result.


Example here shows a function showing the list of chocolates in a dialog . The list contains an image an text on the right of it.
The layout I made is :


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical" android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:background="@color/bgcolour_sharepoints">


  <TextView
      android:id="@+id/dialog_header"
      android:textColor="@color/black"
      android:textSize="18sp"
      android:padding="@dimen/margin_10dp"
      android:layout_width="match_parent"
      android:text="@string/select_language"
      android:layout_height="wrap_content" />
  <View
     android:background="@color/black"
      android:layout_width="match_parent"
      android:layout_height="1dp"/>
  <ListView
      android:id="@+id/listView_chocolate"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"/>
</LinearLayout>


Function to show the dialog :
String selectedVal ;
   public void showChocListDialog(final Context context, Activity activity) {


       ListAdapter arrayAdapter;
       final ArrayList<Chocolate> arraylist = new ArrayList<>();
//these drawables are present in the drawable folder
       Integer[] imageId = {
               R.drawable.silk,
               R.drawable.dairymilk
       };


// chocolates_list is a string array in the strings.xml file
       final String[] chocolates= context.getResources().getStringArray(R.array.chocolates_list);
       for (int i = 0; i < chocolates.length; i++) {
           Language chocObj = new Language(languages[i].substring(3, languages[i].length()), imageId[i]);
           arraylist.add(chocObj);
       }
       arrayAdapter = new ChocolateArrayAdpater(activity, arraylist);


       dialog = new Dialog(mContext);
       dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);


      View view = mActivity.getLayoutInflater().inflate(R.layout.dialog_layout, null);


       ListView lv = (ListView) view.findViewById(R.id.listView_chocolate);
       TextView tv_header = (TextView) view.findViewById(R.id.dialog_header);
       lv.setAdapter(arrayAdapter);


       lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
           @Override
           public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
               selectedVal = arraylist.get(position).getName();
//will dicsuss about this line later.    
mListener._func_chocolateSetup();
               Log.d(TAG, "chosen " + selectedVal);
               dialog.dismiss();      
           }
       });
       dialog.setContentView(view);
       dialog.show();
   }


The above function shows how to display a dialog with a list view of items . Items contains an imageview and a text view . On clicking the an item from the list , we save the selected item in a variable to be used later .
Note : This method is written in a common class , u can name it anything like Utility or Utils, Common as per your conveniece.


As you can see we have used a model class in this named Chocolate and an array adapter named ChocolateArrayAdapater , well this is required to populate the list .
Their definition is as below:


   static Chocolate {
       private String name;
       private int image_id;


       Chocolate(String name, int imageid) {
           this.name = name;
           this.image_id = imageid;
       }


       public String getName() {
           return name;
       }


       public void setName(String name) {
           this.name = name;
       }


       int getImage_id() {
           return image_id;
       }


       public void setImage_id(int image_id) {
           this.image_id = image_id;
       }
   }


//the array adpater definition
   private class ChocolateArrayAdpater extends ArrayAdapter<Chocolate> {


       private final List<Chocolate> list;
       private final Activity context;


       class ViewHolder {
           protected TextView name;
           ImageView iv_country;
       }


       ChocolateArrayAdpater(Activity context, List<Chocolate> list) {
           super(context, R.layout.Chocolate_row, list);
           this.context = context;
           this.list = list;
       }


       @NonNull
       @Override
       public View getView(int position, View convertView, ViewGroup parent) {
           View view;
           if (convertView == null) {
               LayoutInflater inflator = context.getLayoutInflater();
               view = inflator.inflate(R.layout.Chocolate_row, null);
               final ChocolateArrayAdpater.ViewHolder viewHolder = new ChocolateArrayAdpater.ViewHolder();
               viewHolder.name = (TextView) view.findViewById(R.id.list_value);
               viewHolder.iv_country = (ImageView) view.findViewById(R.id.iv_country);
               view.setTag(viewHolder);
           } else {
               view = convertView;
           }


           ChocolateArrayAdpater.ViewHolder holder = (ChocolateArrayAdpater.ViewHolder) view.getTag();
           holder.name.setText(list.get(position).getName());
           holder.iv_country.setBackgroundDrawable(context.getResources().getDrawable(list.get(position).getImage_id()));
           return view;
       }
   }


No for multiple activity or fragment to interact with this piece of code in the Common class we needs a mediator , this cannot be done directly.
So we define and interface in the same Common Class in our project like this :


   public interface I_Chocolatestup
   {
       void _func_chocolateSetup();
   }


In the common class for interaction with the activities and fragments in your app , we do this :


//the mListener to initialize the class which will receive the call back
  private I_Chocolatestup mListener;
   private final Context mContext;
   private final Activity mActivity;
   public Utility(Context context, I_Chocolatestup listener,Activity mActivity) {
       mContext = context;
       mListener = listener;
       this.mActivity = mActivity;
   }


Remember we wrote a line in the function to show the dialog which we wrote to discuss later . now is the correct time.
mListener._func_chocolateSetup();


This is meant to call the class that will intialiaze its context in the Utility() so that the class gets the callback to perform the action based on the selected values.


Till this point all of the code is to be in the Common Utility class


Now is the part for the Activity/Fragment  class.


For all the classes that want to display this dialog , we implement this interface in them like this:


public class ChocolateSelectionActivity extends WifogFragmentActivity implements Utility.I_Chocolatestup


So we have to override the function in the interface :
   @Override
   public void _func_chocolateSetup() {
     //perform your action whatever you want
   }


Now the final and climax line to trigger the showing of the dialog and initializing the context to the listener to get the call back :


Utility utilObj;
utilObj = new Utility(this,this,this);
utilObj.showChocolateListDialog(this.getActivity(), this.getActivity());


Finally its done. Now use the showChocolateListDialog() as  many places as you want without redundant codes in the classes .


In next blog I will tell you on how can you avoid creation of multiple dialogs from same piece of code.

How to add language header to the Webview

In Android in the webviews, the urls are passed as a plain text . If you wan to send suppose language in the header then its pretty simple.

The language should be in the two alphabet format like en, sv, it  i.e.
en - English 
sv - Swedish 
it  - Italian 

"Accept-Language" is the keyword used to add the header in the webview 

This can be found out easily from the web from many available sites: 

the loadUrl(String url, Map<String, String> extraHeaders) method of the Webview allows to pass the language header.

This is the actual implementation :

Map<String, String> headers = new HashMap<>();
headers.put("Accept-Language",language));
mWebView.loadUrl(currentUrl,headers);

Localization implementation in android apps

The Language translation for the android apps to support the Localization. In android apps, if you want to support multiple languages ...