Sunday 31 July 2011

Using Java script in Android WebView through JSInterface

This is a very powerful way to implement java script into Android web view component using JavascriptInterface. You can easily invoke an android method from a WebView.

Let say :

There is a WebView ....
WebView web = new WebView();

Now we need to make it js enabled ...
WebSettings settings = web.getSettings();
settings.setJavaScriptEnabled(true);

Now , need to point it to our custom JSInterface class ..
web.addJavascriptInterface(new JSInterface(), "jsinterface");

Now, load a custom html to load ...

String html = new String();
html = ("<html><center><img border=\"0\" onClick=\"window.jsinterface.specialClick('" + parameter_1 + "','" + parameter_2 + "');\" " + " width='60dip' src=\"" + mediaSource + "\"></html>");
web.loadData(html, "text/html", "utf-8");

This html will load a image fetching from either a url or file ( mediaSource ) and we want to track the onClick method of WebView in the Android code itself. So, there is a method in the JSInterface called specialClick() which will do it. And to invoke the method into HTML code , use the code ..

onClick="window.jsinterface.specialClick('" + parameter_1 + "','" + parameter_2 + "');

Now, the time to write the JSInterface class and specialClick() method.

Create a class named JSInterface and put the code ...


public class JSInterface
{
public void specialClick(String param1, String param2)
{
Log.d("CZ","param1..." + param1 + " , param2..." + param2);
handler.post(new Runnable()
{
public void run()
{
}
});
}
}


In such way , whatever parameters you have passed from HTML onClick method , you will get it in Android code. So, connection between WebView javascript and Android native code is done.

For, further clarification and doubts , you may contact me ....  surojit.pakira@collectivezen.com




Thursday 7 July 2011

Android Simple Accordion or Collapse Panel

After a wise looking on internet I accept that fact , creating an Accordion component  in android which can be easily comparable with HTML/Java Script counterpart is never an easy task.
So, I have tried to develop such a component which may fulfill your requirement. This may not be the best way but one of the ways , for sure.

Here are couple of screen shots of the example :


First create a layout xml and give it the name "accordian.xml". Put the bellow code in it :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent" android:background="#ffffff"
android:layout_height="fill_parent">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="center">
<TextView android:text="Location" android:id="@+id/text1" android:padding="5dip" android:background="#005555"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/panel1" android:visibility="gone"  android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:layout_margin="2dip" android:text="Item1" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item2" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item3" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
    </LinearLayout>
    <LinearLayout android:layout_marginTop="2dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="center">
<TextView android:text="Symptons" android:id="@+id/text2" android:padding="5dip" android:background="#005555"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/panel2" android:visibility="gone" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:layout_margin="2dip" android:text="Item1" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item2" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item3" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
    </LinearLayout>
    <LinearLayout android:layout_marginTop="2dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="center">
<TextView android:text="Location" android:id="@+id/text3" android:padding="5dip" android:background="#005555"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/panel3" android:visibility="gone" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:layout_margin="2dip" android:text="Item1" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item2" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item3" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
    </LinearLayout>
    <LinearLayout android:layout_marginTop="2dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="center">
<TextView android:text="Character" android:id="@+id/text4" android:padding="5dip" android:background="#005555"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/panel4" android:visibility="gone" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:layout_margin="2dip" android:text="Item1" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item2" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item3" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
    </LinearLayout>
    <LinearLayout android:layout_marginTop="2dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="center">
<TextView android:text="Factors" android:id="@+id/text5" android:padding="5dip" android:background="#005555"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/panel5" android:visibility="gone" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:layout_margin="2dip" android:text="Item1" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item2" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:layout_margin="2dip" android:text="Item3" android:padding="5dip" android:background="#777777"  android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
    </LinearLayout>
<ListView android:id="@android:id/list" android:layout_width="fill_parent" android:visibility="gone"
android:layout_height="340dip"  android:drawSelectorOnTop="false"  android:dividerHeight="0px"/>
</LinearLayout>


Create java file and name it "AccordianSampleActivity.java" and put the bellow code in it :


import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.animation.ScaleAnimation;
import android.view.animation.Transformation;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.LinearLayout.LayoutParams;

public class AccordianSampleActivity extends ListActivity implements OnClickListener
{
public OnLongClickListener longClickListner;
LinearLayout panel1,panel2,panel3,panel4,panel5;
TextView text1,text2,text3,text4,text5;
View openLayout;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.accordian);

panel1 = (LinearLayout) findViewById(R.id.panel1);
panel2 = (LinearLayout) findViewById(R.id.panel2);
panel3 = (LinearLayout) findViewById(R.id.panel3);
panel4 = (LinearLayout) findViewById(R.id.panel4);
panel5 = (LinearLayout) findViewById(R.id.panel5);

//panel1.setVisibility(View.VISIBLE);

//panel1.setVisibility(View.VISIBLE);

//Log.v("CZ","height at first ..." + panel1.getMeasuredHeight());

text1 = (TextView) findViewById(R.id.text1);
text2 = (TextView) findViewById(R.id.text2);
text3 = (TextView) findViewById(R.id.text3);
text4 = (TextView) findViewById(R.id.text4);
text5 = (TextView) findViewById(R.id.text5);

text1.setOnClickListener(this);
text2.setOnClickListener(this);
text3.setOnClickListener(this);
text4.setOnClickListener(this);
text5.setOnClickListener(this);

}
@Override
public void onClick(View v)
{
hideOthers(v);
}
private void hideThemAll()
{
if(openLayout == null) return;
if(openLayout == panel1)
panel1.startAnimation(new ScaleAnimToHide(1.0f, 1.0f, 1.0f, 0.0f, 500, panel1, true));
if(openLayout == panel2)
panel2.startAnimation(new ScaleAnimToHide(1.0f, 1.0f, 1.0f, 0.0f, 500, panel2, true));
if(openLayout == panel3)
panel3.startAnimation(new ScaleAnimToHide(1.0f, 1.0f, 1.0f, 0.0f, 500, panel3, true));
if(openLayout == panel4)
panel4.startAnimation(new ScaleAnimToHide(1.0f, 1.0f, 1.0f, 0.0f, 500, panel4, true));
if(openLayout == panel5)
panel5.startAnimation(new ScaleAnimToHide(1.0f, 1.0f, 1.0f, 0.0f, 500, panel5, true));
}
private void hideOthers(View layoutView)
{
{
int v;
if(layoutView.getId() == R.id.text1)
{
v = panel1.getVisibility();
if(v != View.VISIBLE)
{
panel1.setVisibility(View.VISIBLE);
Log.v("CZ","height..." + panel1.getHeight());
}

//panel1.setVisibility(View.GONE);
//Log.v("CZ","again height..." + panel1.getHeight());
hideThemAll();
if(v != View.VISIBLE)
{
panel1.startAnimation(new ScaleAnimToShow(1.0f, 1.0f, 1.0f, 0.0f, 500, panel1, true));
}
}
else if(layoutView.getId() == R.id.text2)
{
v = panel2.getVisibility();
hideThemAll();
if(v != View.VISIBLE)
{
panel2.startAnimation(new ScaleAnimToShow(1.0f, 1.0f, 1.0f, 0.0f, 500, panel2, true));
}
}
else if(layoutView.getId() == R.id.text3)
{
v = panel3.getVisibility();
hideThemAll();
if(v != View.VISIBLE)
{
panel3.startAnimation(new ScaleAnimToShow(1.0f, 1.0f, 1.0f, 0.0f, 500, panel3, true));
}
}
else if(layoutView.getId() == R.id.text4)
{
v = panel4.getVisibility();
hideThemAll();
if(v != View.VISIBLE)
{
panel4.startAnimation(new ScaleAnimToShow(1.0f, 1.0f, 1.0f, 0.0f, 500, panel4, true));
}
}
else if(layoutView.getId() == R.id.text5)
{
v = panel5.getVisibility();
hideThemAll();
if(v != View.VISIBLE)
{
panel5.startAnimation(new ScaleAnimToShow(1.0f, 1.0f, 1.0f, 0.0f, 500, panel5, true));
}
}
}
}

public class ScaleAnimToHide extends ScaleAnimation
{

       private View mView;

       private LayoutParams mLayoutParams;

       private int mMarginBottomFromY, mMarginBottomToY;

       private boolean mVanishAfter = false;

       public ScaleAnimToHide(float fromX, float toX, float fromY, float toY, int duration, View view,boolean vanishAfter)
       {
           super(fromX, toX, fromY, toY);
           setDuration(duration);
           openLayout = null;
           mView = view;
           mVanishAfter = vanishAfter;
           mLayoutParams = (LayoutParams) view.getLayoutParams();
           int height = mView.getHeight();
           mMarginBottomFromY = (int) (height * fromY) + mLayoutParams.bottomMargin - height;
           mMarginBottomToY = (int) (0 - ((height * toY) + mLayoutParams.bottomMargin)) - height;
         
           Log.v("CZ","height..." + height + " , mMarginBottomFromY...." + mMarginBottomFromY  + " , mMarginBottomToY.." +mMarginBottomToY);
       }

       @Override
       protected void applyTransformation(float interpolatedTime, Transformation t)
       {
           super.applyTransformation(interpolatedTime, t);
           if (interpolatedTime < 1.0f)
           {
               int newMarginBottom = mMarginBottomFromY + (int) ((mMarginBottomToY - mMarginBottomFromY) * interpolatedTime);
               mLayoutParams.setMargins(mLayoutParams.leftMargin, mLayoutParams.topMargin,mLayoutParams.rightMargin, newMarginBottom);
               mView.getParent().requestLayout();
               //Log.v("CZ","newMarginBottom..." + newMarginBottom + " , mLayoutParams.topMargin..." + mLayoutParams.topMargin);
           }
           else if (mVanishAfter)
           {
               mView.setVisibility(View.GONE);
           }
       }
}
public class ScaleAnimToShow extends ScaleAnimation
{

       private View mView;

       private LayoutParams mLayoutParams;

       private int mMarginBottomFromY, mMarginBottomToY;

       private boolean mVanishAfter = false;

       public ScaleAnimToShow(float toX, float fromX, float toY, float fromY, int duration, View view,boolean vanishAfter)
       {
           super(fromX, toX, fromY, toY);
           openLayout = view;
           setDuration(duration);
           mView = view;
           mVanishAfter = vanishAfter;
           mLayoutParams = (LayoutParams) view.getLayoutParams();
           mView.setVisibility(View.VISIBLE);
           int height = mView.getHeight();
           //mMarginBottomFromY = (int) (height * fromY) + mLayoutParams.bottomMargin + height;
           //mMarginBottomToY = (int) (0 - ((height * toY) + mLayoutParams.bottomMargin)) + height;
         
           mMarginBottomFromY = 0;
           mMarginBottomToY = height;
         
           Log.v("CZ",".................height..." + height + " , mMarginBottomFromY...." + mMarginBottomFromY  + " , mMarginBottomToY.." +mMarginBottomToY);
       }

       @Override
       protected void applyTransformation(float interpolatedTime, Transformation t)
       {
           super.applyTransformation(interpolatedTime, t);
           if (interpolatedTime < 1.0f)
           {
               int newMarginBottom = (int) ((mMarginBottomToY - mMarginBottomFromY) * interpolatedTime) - mMarginBottomToY;
               mLayoutParams.setMargins(mLayoutParams.leftMargin, mLayoutParams.topMargin,mLayoutParams.rightMargin, newMarginBottom);
               mView.getParent().requestLayout();
               //Log.v("CZ","newMarginBottom..." + newMarginBottom + " , mLayoutParams.topMargin..." + mLayoutParams.topMargin);
           }
       }

}
}


Before compilation , make sure you have made an entry in the manifest file for the new activity.

In this app , I have implemented the accordion panel what I just said..
https://market.android.com/details?id=com.lcs.mmp.lite