How to display the pdf in Android ?


Quick start incorporating a PDF viewing activity into your project:

1) Add PdfViewer.jar into your project’s build path

2) Copy the following drawable resources from PdfViewer/res/drawable into YourProject/res/drawable left_arrow.png right_arrow.png zoom_in.png zoom_out.png

3) Copy the following layout resources from PdfViewer/res/layout into YourProject/res/layout dialog_pagenumber.xml pdf_file_password.xml

4) Derive your PDF activity from net.sf.andpdf.pdfviewer.PdfViewerActivity

5) Using the default drawables and layouts:


public int getPreviousPageImageResource() { return R.drawable.left_arrow; }

public int getNextPageImageResource() { return R.drawable.right_arrow; }

public int getZoomInImageResource() { return R.drawable.zoom_in; }

public int getZoomOutImageResource() { return R.drawable.zoom_out; }

public int getPdfPasswordLayoutResource() { return R.layout.pdf_file_password; }

public int getPdfPageNumberResource() { return R.layout.dialog_pagenumber; }

public int getPdfPasswordEditField() { return R.id.etPassword; }

public int getPdfPasswordOkButton() { return R.id.btOK; }

public int getPdfPasswordExitButton() { return R.id.btExit; }

public int getPdfPageNumberEditField() { return R.id.pagenum_edit; }

6) Invoke your PdfViewActivity derived with the following code:


Intent intent = new Intent(this, YourPdfViewerActivity.class);

intent.putExtra(PdfViewerActivity.EXTRA_PDFFILENAME, "PATH TO PDF GOES HERE");

startActivity(intent);

Download the source code and demo code from below link here

 

 

EDIT:  Another pdf viewer source for free  at github.

https://github.com/rameshakulapc/PDFViewer

Find the reference  Post by Andhradroid.

How to implement swipe delete in android like iphone ?


Step 1: Just extends below class and implement getListview method.

Step 2: The below MainActivity demonstrates in which direction single item should be swiped and gives the item position of clicked item. We have to manage it in adapter to swipe-delete operation from our own scratch.

SwipeListViewActivity.java:

public abstract class SwipeListViewActivity extends Activity {

private ListView list;
private int REL_SWIPE_MIN_DISTANCE;
private int REL_SWIPE_MAX_OFF_PATH;
private int REL_SWIPE_THRESHOLD_VELOCITY;

/**
*
* @return ListView
*/
public abstract ListView getListView();

/**
*
* @param isRight
* Swiping direction
* @param position
* which item position is swiped
*/
public abstract void getSwipeItem(boolean isRight, int position);

/**
* For single tap/Click
*
* @param adapter
* @param position
*/
public abstract void onItemClickListener(ListAdapter adapter, int position);

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

DisplayMetrics dm = getResources().getDisplayMetrics();
REL_SWIPE_MIN_DISTANCE = (int) (120.0f * dm.densityDpi / 160.0f + 0.5);
REL_SWIPE_MAX_OFF_PATH = (int) (250.0f * dm.densityDpi / 160.0f + 0.5);
REL_SWIPE_THRESHOLD_VELOCITY = (int) (200.0f * dm.densityDpi / 160.0f + 0.5);
}

@Override
protected void onResume() {
super.onResume();
list = getListView();
if (list == null) {
new Throwable("Listview not set exception");
}

@SuppressWarnings("deprecation")
final GestureDetector gestureDetector = new GestureDetector(
new MyGestureDetector());

View.OnTouchListener gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
list.setOnTouchListener(gestureListener);

}

private void myOnItemClick(int position) {
if (position < 0)
return;
onItemClickListener(list.getAdapter(), position);

}

class MyGestureDetector extends SimpleOnGestureListener {

private int temp_position = -1;

// Detect a single-click and call my own handler.
@Override
public boolean onSingleTapUp(MotionEvent e) {

int pos = list.pointToPosition((int) e.getX(), (int) e.getY());
myOnItemClick(pos);
return true;
}

@Override
public boolean onDown(MotionEvent e) {

temp_position = list
.pointToPosition((int) e.getX(), (int) e.getY());
return super.onDown(e);
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
if (Math.abs(e1.getY() - e2.getY()) > REL_SWIPE_MAX_OFF_PATH)
return false;
if (e1.getX() - e2.getX() > REL_SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > REL_SWIPE_THRESHOLD_VELOCITY) {

int pos = list
.pointToPosition((int) e1.getX(), (int) e2.getY());

if (pos >= 0 && temp_position == pos)
getSwipeItem(false, pos);
} else if (e2.getX() - e1.getX() > REL_SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > REL_SWIPE_THRESHOLD_VELOCITY) {

int pos = list
.pointToPosition((int) e1.getX(), (int) e2.getY());
if (pos >= 0 && temp_position == pos)
getSwipeItem(true, pos);

}
return false;
}

}

}
<h3>

MainActivity.java:

public class MainActivity extends SwipeListViewActivity {

private ListView mListView;
 private ArrayAdapter<String> mAdapter;

@Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 mListView = (ListView) findViewById(R.id.listView1);
 mAdapter = new ArrayAdapter<String>(this,
 android.R.layout.simple_list_item_1, new String[] { "Item 1",
 "Item 2", "Item 2", "Item 3", "Item 4", "Item 5" });
 mListView.setAdapter(mAdapter);
 }

@Override
 public ListView getListView() {
 return mListView;
 }

@Override
 public void getSwipeItem(boolean isRight, int position) {
 Toast.makeText(this,
 "Swipe to " + (isRight ? "right" : "left") + " direction",
 Toast.LENGTH_SHORT).show();
 }

@Override
 public void onItemClickListener(ListAdapter adapter, int position) {
 Toast.makeText(this, "Single tap on item position " + position,
 Toast.LENGTH_SHORT).show();
 }

}

Get the source code from the following link .
Let you comment on posts and encourage me for nice posts in future…

Service Tutorial in android Part-II


Continued from service tutorial-I…,

3. Service using Messenger:

Now i am going to explain Working with messengers in service:

If you need to be able to write a Service that can perform complicated communication with clients in remote processes (beyond simply the use of Context.startService to send commands to it), then you can use the Messenger class instead of writing full AIDL files.

An example of a Service that uses Messenger as its client interface is shown here. First is the Service itself, publishing a Messenger to an internal Handler when bound:


public class MessengerService extends Service {
 /** Command to the service to display a message */
 static final int MSG_SAY_HELLO = 1;

/**
 * Handler of incoming messages from clients.
 */
 class IncomingHandler extends Handler {
 @Override
 public void handleMessage(Message msg) {
 switch (msg.what) {
 case MSG_SAY_HELLO:
 Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
 break;
 default:
 super.handleMessage(msg);
 }
 }
 }

/**
 * Target we publish for clients to send messages to IncomingHandler.
 */
 final Messenger mMessenger = new Messenger(new IncomingHandler());

/**
 * When binding to the service, we return an interface to our messenger
 * for sending messages to the service.
 */
 @Override
 public IBinder onBind(Intent intent) {
 Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
 return mMessenger.getBinder();
 }
 }

—————————————————————————————————
If we want to make this service run in a remote process (instead of the standard one for its .apk), we can use android:process in its manifest tag to specify one:

<service android:name=”MessengerService”
android:process=”:remote” />

Note that the name “remote” chosen here is arbitrary, and you can use other names if you want additional processes. The ‘:’ prefix appends the name to your package’s standard process name.

With that done, clients can now bind to the service and send messages to it. Note that this allows clients to register with it to receive messages back as well:


public class ServiceUsingMessangerActivity extends Activity {
 /** Messenger for communicating with the service. */
 Messenger mService = null;

/** Flag indicating whether we have called bind on the service. */
 boolean mBound;

/**
 * Class for interacting with the main interface of the service.
 */
 private ServiceConnection mConnection = new ServiceConnection() {
 public void onServiceConnected(ComponentName className, IBinder service) {
 // This is called when the connection with the service has been
 // established, giving us the object we can use to
 // interact with the service. We are communicating with the
 // service using a Messenger, so here we get a client-side
 // representation of that from the raw IBinder object.
 mService = new Messenger(service);
 mBound = true;
 }

public void onServiceDisconnected(ComponentName className) {
 // This is called when the connection with the service has been
 // unexpectedly disconnected -- that is, its process crashed.
 mService = null;
 mBound = false;
 }
 };

public void sayHello(View v) {
 if (!mBound) return;
 // Create and send a message to the service, using a supported 'what' value
 Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
 try {
 mService.send(msg);
 } catch (RemoteException e) {
 e.printStackTrace();
 }
 }

@Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 }

@Override
 protected void onStart() {
 super.onStart();
 // Bind to the service
 bindService(new Intent(this, MessengerService.class), mConnection,Context.BIND_AUTO_CREATE);
 }

@Override
 protected void onStop() {
 super.onStop();
 // Unbind from the service
 if (mBound) {
 unbindService(mConnection);
 mBound = false;
 }
 }
 }

4. Service using Remote AIDL files:

Each application in Android runs in its own process. An application cannot directly access another application’s memory space. This is called application sand-boxing.

In order to allow cross-application communication, Android provides an implementation of interprocess communication (IPC) protocol. IPC protocols tend to get complicated because of all the marshaling/un marshaling of data that is necessary.

To help with this, Android provides Android Interface Definition Language, or AIDL. It is a lightweight implementation of IPC using a syntax that is very familiar to Java developers, and a tool that automates the stub creation.

In order to allow for one application to call into another, we typically have to:

1. Define the AIDL interface:

AIDL interface looks like a general java interface.By default,AIDL supports the following data types:

-> All primitive types in java (such as int,long,char,boolean)

2. Implement the interface:

3. Expose the interface to clients.

IMyInterface.aidl:

package com.ramesh.services.aidl.demo;

interface IMyInterface
{
 void setUserName(in String name);
 String getName();
}

ServiceUsingAidl.java:

public class ServiceUsingAidl extends Service {

private String userName;

@Override
 public IBinder onBind(Intent intent) {
 return mBinder;
 }

private IMyInterface.Stub mBinder = new IMyInterface.Stub() {

@Override
 public void setUserName(String name) throws RemoteException {

userName = name;
 }

@Override
 public String getName() throws RemoteException {
 return userName;
 }
 };
}

AidlDemo.java:


public class AidlDemo extends Activity {

public static final String TAG = "Aidl Demo";
 private IMyInterface mService;

@Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);

Intent serviceIntent = new Intent(this, ServiceUsingAidl.class);
 bindService(serviceIntent, conn, Service.BIND_AUTO_CREATE);

Button btn = (Button) findViewById(R.id.button1);
 btn.setOnClickListener(setNameListener);

Button btn2 = (Button) findViewById(R.id.button1);
 btn2.setOnClickListener(getNameListener);

}

private ServiceConnection conn = new ServiceConnection() {

@Override
 public void onServiceDisconnected(ComponentName name) {
 Log.i(TAG, "Service disconnected.");
 }

@Override
 public void onServiceConnected(ComponentName name, IBinder service) {
 Log.i(TAG, "Service connected.");
 mService = (IMyInterface) service;
 }
 };

private OnClickListener setNameListener = new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 if (mService != null) {
 try {
 mService.setUserName("Andorid world");
 } catch (RemoteException e) {
 e.printStackTrace();
 }
 }
 }
 };
 private OnClickListener getNameListener = new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 if (mService != null) {
 try {
 String str = mService.getName();
 Toast.makeText(AidlDemo.this, str, Toast.LENGTH_SHORT)
 .show();
 } catch (RemoteException e) {
 e.printStackTrace();
 }
 }
 }
 };
}

In manifest, we add service like a simple service.

5. IntentService:

While the base class for creating a Service is the Service class you can also implement IntentService. The IntentService is used to perform a certain task in the background. Once done, the instance of IntentService terminate itself automatically. Examples for its usage would be to download a certain resources from the Internet. The IntentService class offers the onHandleIntent() method which will be asynchronously called by the Android system.

                                           It is advisable to use thread/asynTask or Service to handle long running task such as file I/O, internet access etc. IntentService is simple, easy to use and take care of many hectic tasks for You.Read more about IntentService at developer.android. A simple use case of the topic can be:

  • Your activity send a web request to IntentService to process
  • Your IntentService execute that request using DefaultHttpClient
  • And Return results (whatever, true,false list of objects/records etc) back to the calling activity

Now the task is to return the results back to the activity.  There are two options available either we can use Broadcast receiver or ResultReceiver

  1. Broadcast should be used if you want to send data/notifications across applications, whenever you send broadcast its sent system wide read more about broadcast receivers at developer.android.
  2. Result receiver is an interface you implement and pass it to the intentService through putExtra. IntentService then fetch this object and call its receiver.send function to send anything (in bundle) to calling activity[who started the intentservice]. Result receiver has preference over broadcast receivers if your all communication is internal to your application.
public class CheckIntentService extends IntentService {

private int count;
 public static final int INIT = 1;
 public static final int RUNNING = 2;
 public static final int END = 3;

public CheckIntentService()
 {
 super("Downloading");
 }

@Override
 protected void onHandleIntent(Intent intent) {
 count = 0;
 ResultReceiver receiver = intent.getParcelableExtra("receiver");
 Bundle bundle = new Bundle();
 bundle.putString("message", "Init the service");

receiver.send(INIT, bundle);

bundle = new Bundle();

while (count < 10) {
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 bundle.putString("message", "Running the service");
 bundle.putInt("count", count);
 receiver.send(RUNNING, bundle);
 count++;
 }
 bundle = new Bundle();
 bundle.putString("message", "End of the service");
 bundle.putInt("count", count);
 receiver.send(END, bundle);
 }
}

public class IntentServiceDemo extends Activity {

public static final String TAG = "IntentServiceDemo";

// private ResultReceiver receiver = new ResultReceiver(new Handler()) ;
 ResultReceiver r = new ResultReceiver(new Handler()) {
 @Override
 protected void onReceiveResult(int resultCode, Bundle resultData) {
 String str = "";
 if (resultCode == CheckIntentService.INIT) {
 str = resultData.getString("message");
 Log.i(TAG, str);
 } else if (resultCode == CheckIntentService.RUNNING
 || resultCode == CheckIntentService.END) {
 str = resultData.getString("message");
 int count = resultData.getInt("count", 0);
 Log.i(TAG, "message:" + str);
 Log.i(TAG, "count:" + count);
 }

}
 };

@Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);

setContentView(R.layout.main);

findViewById(R.id.button1).setOnClickListener(new OnClickListener() {

@Override
 public void onClick(View v) {

Intent intentService = new Intent(IntentServiceDemo.this,
 CheckIntentService.class);
 intentService.putExtra("receiver", r);
 startService(intentService);

}
 });

}

}

Note:  Don’t use constructor with parameter in IntentService extended class.It shows an exception.

public CheckIntentService(String name)
{
super(“Downloading”);
}

 
Feel free to comment on my posts.............

Service Tutorial in android Part-I


Service:

A service is a task that runs in the background without the user’s direct interaction, similar to a Unix daemon. For example, consider a music player. The music may be started by an activity, but you want it to keep playing even when the user has moved on to a different program. So, the code that does the actual playing should be in a service. Later,another activity may bind to that service and tell it to switch tracks or stop playing. Android comes with many services built in, along with convenient APIs to access them.

      A Service is a component which runs in the background, without interacting with the user. Every developer can create new Services in his application. Services support true multitasking for Android, as they can run in their own process. If you use threads in Activities their are still connected to the life-cycle of Activities and the Android system may decide to terminate them at any point in point.

For information about services:  http://developer.android.com/reference/android/app/Service.html#RemoteMessengerServiceSample

The following topics are covered in this topic.

  1. Local Services
  2. Service using Binder
  3. Service using Messanger
  4. Serivice using Remote AIDL files
  5. Intent Service

1. Local Services:

We can start the service in two ways .

step 1:
Intent intent=new Intent(context,ServiceClassName.class);
startService(intent);
step 2:
Intent intent=new Intent(“com.ramesh.myservice.ACTION”);
startService(intent);

When we start service using step 2, make sure that adding the action in manifest file.


<service android:name="BindingService" >
 <intent-filter>
 <action android:name="com.ramesh.myservice.ACTION" >
 </action>
 </intent-filter>
 </service>

SimpleService.java:

 public class SimpleService extends Service
 {
 @Override
 public IBinder onBind(Intent arg0)
 {
 return null;
 }
 @Override
 public void onCreate()
 {
 super.onCreate();
 Toast.makeText(this,"Service created ...", Toast.LENGTH_LONG).show();
 }
 @Override
 public void onDestroy() {
 super.onDestroy();
 Toast.makeText(this, "Service destroyed ...", Toast.LENGTH_LONG).show();
 }
 }

In Activity take two buttons for testing , start the service with one button and stop the service with another.

You can choose one of the two steps to start the service.

2. Services using binder:

In Activity we are going to the bind service to communicating with it.

1. In oncreate method, we are binding the service using following statement.

bindService(new Intent(this, BindingService.class), conn,
Service.BIND_AUTO_CREATE);

2.Make sure that unbind the service connection  in onDestroy method Otherwise it gives service connection leaked exception.

  unbindService(conn);

3.When create the IBinder in service, its better to use WeakReference.This bug is mentioned in this blog.

private MyBinder mService;

 private ServiceConnection conn = new ServiceConnection()
 {
 @Override
 public void onServiceDisconnected(ComponentName name)
 {
 //service is disconnected!
 }

@Override
 public void onServiceConnected(ComponentName name, IBinder service)
 {
 //Service is connected.
 mService = (MyBinder) service;
 ((Button)findViewById(R.id.button1)).setText(mService.getName());
 mService.setName("Joy!");
 }
 };

/***BindingService.java:***/

public class BindingService extends Service {

public static final String MY_CUSTOM_ACTION = "com.ramesh.myservice.ACTION";
 private MyBinder<BindingService> binder;
 private String name = "Hi";

@Override
 public IBinder onBind(Intent intent) {
 binder = new MyBinder<BindingService>(this);
 return binder;
 }

@Override
 public int onStartCommand(Intent intent, int flags, int startId) {
 return START_STICKY;
 }

public class MyBinder<T> extends Binder implements IMybinder {
 private WeakReference<T> mService;

public MyBinder(T service) {
 mService = new WeakReference<T>(service);
 }

public T getService() {
 return mService.get();
 }

@Override
 public String getName() {

Random r = new Random();
 return name + "=> your lucky number is:" + r.nextInt(100);
 }

@Override
 public void setName(String newname) {
 name = newname;
 }
 }
}

 /** Interface setting the name and getting the name.**/

 public interface IMybinder
 {
 public String getName();

 public void setName(String name);
 }

Continue to be service tutorial-II…..

Custom spinner widget in android ?


Android Spinner has problems like.,

1.OnItemSelected listener will be fired when data is loadint at first time.

2.We can’t give label to the spinner(by default text).

Hbspinner.java overcomes this problems as per our basic need.

==>Hbspinner extends from button.It is added more methods seems to be Android spinner

==>Hbspinner provides Four types of spinners

=>Normal spinner: which is working just like Android spinner.

=>singleChoice spinner: spinner populates with single choice items.

=>multipleChoice spinner: spinner populates with multi choice items(with checkboxes).you can select more items

=>spinner using adapter:spinner is populating by using adapter.(in my example i am using android default layout: “android.R.layout.select_dialog_item”)

attr.xml:

<pre><?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="spinner">
 <attr name="spinnervaluearray" format="reference" />
 <attr name="prompt" format="string" />
 <attr name="src" format="reference" />
 <attr name="mode">
 <enum name="single" value="0" />
 <enum name="multiple" value="1" />
 <enum name="single_radio" value="2" />
 </attr>
 </declare-styleable>

</resources>

In layout/main.xml ,your declaration should be like this.


<pre><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:pref="http://schemas.android.com/apk/res/com.ramesh.spinner.demo"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:gravity="center"
 android:orientation="vertical" >
<com.ramesh.spinner.demo.HbSpinner
 android:id="@+id/hbSpinner2"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:drawableRight="@drawable/arrow_down_float"
 android:text="Using Xml Attributes for Spinner "
 pref:mode="single"
 pref:prompt="Web Development"
 pref:spinnervaluearray="@array/web"
 pref:src="@drawable/ic_launcher" />
</LinearLayout>

Hbspinner.java:


package com.ramesh.spinner.demo;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;

public class HbSpinner extends Button {

private AlertDialog dialog;
 private final static int INVALID = -1;
 private CharSequence[] singeItems;
 private OnSingleItemCallback listener;
 private static OnMultiItemsSelectionCallback multilistener;
 private String title = null;
 private int icon = INVALID;
 private Drawable iconDrawable;
 private int mMode;
 public static final int SINGLE = 0;
 public static final int MULTIPLE = 1;
 public static final int SINGLE_RADIO = 2;

public HbSpinner(Context context) {
 super(context, null);
 }

public HbSpinner(Context context, AttributeSet attrs) {
 super(context, attrs);
 if (attrs != null) {
 TypedArray a = getResources().obtainAttributes(attrs,
 R.styleable.spinner);
 int count = a.getIndexCount();

for (int i = 0; i < count; i++) {
 int type = a.getIndex(i);
 switch (type) {
 case R.styleable.spinner_mode: {
 setChoiceMode(a.getInt(type, 0));
 }
 break;
 case R.styleable.spinner_spinnervaluearray: {
 singeItems = a.getTextArray(type);
 }
 break;
 case R.styleable.spinner_prompt: {
 title = a.getString(type);
 }
 break;
 case R.styleable.spinner_src: {
 iconDrawable = a.getDrawable(type);
 }
 break;
 default:
 break;
 }
 }
 a.recycle();
 }

init();
 }

public void init() {
 setOnClickListener(onClick);
 }

public void setDefaultText(String string) {
 if (string != null)
 this.setText(string);
 }

public void setIcon(int icon) {
 this.icon = icon;
 }

public void setChoiceMode(int mode) {
 if (mode < 3 && mode > INVALID)
 mMode = mode;
 // else
 // new Exception(new Throwable("Illegal Mode selection"));
 }

public void setPrompt(String title) {
 this.title = title;
 }

public void setSingleDataItems(String[] items) {
 singeItems = items;
 mMode = SINGLE;

}

/**
 * Set on single items selection.
 *
 * @param callback
 */
 public void setOnSingleItemSelectedListener(OnSingleItemCallback callback) {
 listener = callback;
 }

/**
 * Set on Multiple items selection
 *
 * @param listener
 */
 public void setOnMultiItemSelectedListener(
 OnMultiItemsSelectionCallback listener) {
 multilistener = listener;
 }

@Override
 protected void onDetachedFromWindow() {
 super.onDetachedFromWindow();
 if (dialog != null && dialog.isShowing())
 dialog.dismiss();
 }

public OnClickListener onClick = new View.OnClickListener() {

@Override
 public void onClick(View v) {

if (adapter != null) {
 popupSpinnerAdapter();
 } else if (SINGLE == mMode) {
 popupSingleSpinner();
 } else if (mMode == MULTIPLE) {
 popupMultipleSpinner();
 } else if (mMode == SINGLE_RADIO) {
 popupSingleRadioSpinner();
 }
 }
 };

public CharSequence[] getItems() {
 return singeItems;
 }

private void popupSingleSpinner() {
 if (dialog != null && dialog.isShowing())
 dialog.dismiss();
 if (singeItems.length == 0) {
 singeItems = new String[] { "" };
 }

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
 if (title != null)
 builder.setTitle(title);
 if (icon != INVALID) {
 builder.setIcon(icon);
 } else if (iconDrawable != null) {
 builder.setIcon(iconDrawable);
 }
 builder.setItems(singeItems, onDialogClick);
 dialog = builder.create();
 dialog.show();
 }

private void popupMultipleSpinner() {
 if (dialog != null && dialog.isShowing())
 dialog.dismiss();
 if (singeItems.length == 0) {
 singeItems = new String[] { "" };
 }

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
 if (title != null)
 builder.setTitle(title);
 if (icon != INVALID) {
 builder.setIcon(icon);
 } else if (iconDrawable != null) {
 builder.setIcon(iconDrawable);
 }
 builder.setMultiChoiceItems(singeItems, null, onMultiClick);

builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {

@Override
 public void onClick(DialogInterface dialog, int which) {
 if (multilistener != null && checkedPositions.length > 0) {
 multilistener.setMultiSelectedItemsCallback(HbSpinner.this,
 checkedPositions);
 checkedPositions = new int[0];
 }
 }
 });
 builder.setNegativeButton("Cancel", null);

dialog = builder.create();
 dialog.show();
 dialog.getListView().setOnItemClickListener(onItemSelected);

}

public DialogInterface.OnClickListener onDialogClick = new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {
 if (mMode == SINGLE_RADIO)
 checkedItem = which;

if (listener != null)
 listener.onItemSelectedListener(HbSpinner.this,
 singeItems[which], which);
 HbSpinner.this.setText(singeItems[which]);
 dialog.dismiss();
 }
 };
 public DialogInterface.OnMultiChoiceClickListener onMultiClick = new DialogInterface.OnMultiChoiceClickListener() {

@Override
 public void onClick(DialogInterface dialog, int which, boolean isChecked) {

}
 };

private int[] checkedPositions = new int[0];
 public OnItemClickListener onItemSelected = new OnItemClickListener() {
 @Override
 public void onItemClick(AdapterView<?> arg0, View arg1, int position,
 long arg3) {
 ListView view = (ListView) arg0;
 SparseBooleanArray sp = view.getCheckedItemPositions();
 checkedPositions = new int[sp.size()];
 for (int i = 0; i < sp.size(); i++)
 checkedPositions[i] = sp.keyAt(i);
 }
 };

private int checkedItem = INVALID;

private void popupSingleRadioSpinner() {
 if (dialog != null && dialog.isShowing())
 dialog.dismiss();
 if (singeItems.length == 0) {
 singeItems = new String[] { "" };
 }

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
 if (title != null)
 builder.setTitle(title);
 if (icon != INVALID) {
 builder.setIcon(icon);
 } else if (iconDrawable != null) {
 builder.setIcon(iconDrawable);
 }
 builder.setSingleChoiceItems(singeItems, checkedItem, onDialogClick);
 dialog = builder.create();
 dialog.show();
 }

public ListAdapter adapter;

public void setAdapter(ListAdapter adapter,
 HbSpinnerAdapterCallback callbackAdapter) {
 this.adapter = adapter;
 this.callbackAdapter = callbackAdapter;
 }

private void popupSpinnerAdapter() {
 if (dialog != null && dialog.isShowing())
 dialog.dismiss();
 AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
 if (title != null)
 builder.setTitle(title);
 if (icon != INVALID) {
 builder.setIcon(icon);
 } else if (iconDrawable != null) {
 builder.setIcon(iconDrawable);
 }
 builder.setAdapter(adapter, new DialogInterface.OnClickListener() {

@Override
 public void onClick(DialogInterface dialog, int which) {
 if (callbackAdapter != null)
 callbackAdapter.onItemselectionAdapter(HbSpinner.this,
 which);
 }
 });// setSingleChoiceItems(singeItems,
 // builder.setItems(singeItems, onDialogClick);
 dialog = builder.create();
 dialog.show();
 }

public void setOnAdapterItemSelectionListener(
 HbSpinnerAdapterCallback callback) {
 callbackAdapter = callback;
 }

public ListAdapter getAdapter() {
 return adapter;
 }

HbSpinnerAdapterCallback callbackAdapter;

interface HbSpinnerAdapterCallback {
 /**
 * Adapter items selection callback
 *
 * @param spinner
 * {@link HbSpinner}
 * @param position
 * clicked position
 */
 public void onItemselectionAdapter(HbSpinner spinner, int position);
 }

interface OnMultiItemsSelectionCallback {

/**
 * Multiple items selection callback
 *
 * @param spinner
 * {@link HbSpinner}
 * @param checked
 * integer array which contains checked indexes
 */
 public void setMultiSelectedItemsCallback(HbSpinner spinner,
 int[] checked);
 }

interface OnSingleItemCallback {
 /**
 * Single items selection callback
 *
 * @param spinner
 * {@link HbSpinner}
 * @param selectedItem
 * selected item
 * @param position
 * selected position
 */
 public void onItemSelectedListener(HbSpinner spinner,
 CharSequence selectedItem, int position);
 }
}

you can find the source code here.
Screenshot:

screen shot

Custom spinner widget

Custom xml layouts in android .


i’ll walk through you how to use the styles and implementing the custom layouts in android.
You can learn the following concepts:

  1. Styles: Styles are used to simplifies our code in xml layout and complexity.
  2. Attributes: Here we can learn the usage of custom attributes.In my example i am creating rating bar.I am introducing in this example, level-list which is used to show the ratings icons.
  3. Level-list: A Drawable that manages a number of alternate Drawables, each assigned a maximum numerical value. Setting the level value of the drawable with setLevel() loads the drawable resource in the level list that has a android:maxLevel value greater than or equal to the value passed to the method.
  4. How to decalare custom layouts in Xml.
  5. How to accept the custom attributes and its values for custom layout in Xml.
Code Explanation:
—————–
  • When we are creating custom layouts we need to define constructor with 2 or 3 parameters.
  • In init() , reading the values which are defined in xml layout and which are defined with custom attributes .Custom attributes are available with attributesParentname_yourAttibutesName (in my example: R.styleable.customratingbar_rating).
  • In switch case first argument is R.styleable.customratingbar_rating, is used to get the current rating.
  • Second argument R.styleable.customratingbar_src, is used to read level-list Xml.
  • Last argument is R.styleable.customratingbar_max, is used to set the maximum rating.
  • ImageView#setImageLevel() is used to load the drawable resource in the level list.

res/values/attr.xml:


<?xml version="1.0" encoding="utf-8"?>
<resources >
 <declare-styleable name="customratingbar">
 <attr name="rating" format="integer"/>
 <attr name="max" format="integer"/>
 <attr name="src" format="reference"/>
 </declare-styleable>

</resources>

res/layout/main.xml:


<!--xmlns:pref="http://schemas.android.com/apk/res/"com.ramesh.customratingbar.demo" is application packag name and pref is your prefix to identify the attributes and assinging the values.-->
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:pref="http://schemas.android.com/apk/res/com.ramesh.customratingbar.demo"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical" >

<com.ramesh.customratingbar.demo.CustomRatingBar
 android:id="@+id/customRatingBar1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 pref:max="5"
 pref:rating="1"
 pref:src="@drawable/layer_list_demo" />

</LinearLayout>

CustomRatingBar.java:

public class CustomRatingBar extends ImageView {

private int currentRating = 0;
 private int maxRating = 0;
 private int ratingResId;
 private LevelListDrawable drawable;
 private OnRatingBarChangeListener listener;

public CustomRatingBar(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 init(context, attrs);
 }

public CustomRatingBar(Context context, AttributeSet attrs) {
 super(context, attrs);
 init(context, attrs);
 }

public void init(Context context, AttributeSet attrs) {
 setOnTouchListener(onTouch);
 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.customratingbar);
 final int n = a.getIndexCount();
 for (int i = 0; i < n; ++i) {
 int attr = a.getIndex(i);
 switch (attr) {
 case R.styleable.customratingbar_rating:
 currentRating = a.getInt(attr, 0);
 setRating(currentRating);
 break;
 case R.styleable.customratingbar_src:
 ratingResId = a.getResourceId(attr, 0);
 try {
 drawable = (LevelListDrawable) LevelListDrawable
 .createFromXml(getResources(), getResources()
 .getXml(ratingResId));
 } catch (NotFoundException e) {
 e.printStackTrace();
 } catch (XmlPullParserException e) {
 e.printStackTrace();
 } catch (IOException e) {
 e.printStackTrace();
 }

setRatingDrawable(drawable);
 break;
 case R.styleable.customratingbar_max:
 maxRating = a.getInt(attr, 0);
 setMax(maxRating);
 break;

}
 }
 a.recycle();
 }

@Override
 public void setImageLevel(int level) {
 super.setImageLevel(level);
 currentRating = level;
 }

public void setRating(int rating) {
 setImageLevel(rating);
 }

public void setRatingDrawable(Drawable drawable) {
 setImageDrawable(drawable);
 }

public void setRatingDrawable(int ratingResId) {

this.ratingResId = ratingResId;
 setImageResource(ratingResId);
 }

public void setMax(int max) {
 maxRating = max;
 }

public void setOnRatingListener(OnRatingBarChangeListener listener) {
 this.listener = listener;
 }

interface OnRatingBarChangeListener {
 public void setOnRatingChageListener(CustomRatingBar ratingbar,
 int rating);
 }

public OnTouchListener onTouch = new OnTouchListener() {

@Override
 public boolean onTouch(View v, MotionEvent event) {
 float rawX = event.getX();
 if (event.getAction() == MotionEvent.ACTION_MOVE) {
 float width = CustomRatingBar.this.getWidth();
 if (width > 0)
 {
 float tem1 = (rawX / width) * 100 * maxRating;
 int perc = (int) tem1 / 100;
 if (perc <= maxRating && perc >= 0) {
 currentRating = perc + 1;
 currentRating = currentRating > maxRating ? maxRating
 : currentRating;
 setImageLevel(currentRating);
 }
 }
 }
 if (event.getAction() == MotionEvent.ACTION_UP) {
 float width = CustomRatingBar.this.getWidth();
 if (width > 0) {
 float temp = (rawX / width) * maxRating;
 int perc = (int) temp;
 if (perc <= maxRating && perc >= 0) {
 currentRating = perc + 1;
 currentRating = currentRating > maxRating ? maxRating
 : currentRating;
 setImageLevel(currentRating);
 listener.setOnRatingChageListener(CustomRatingBar.this,
 currentRating);
 }
 }
 }

return true;
 }
 };
}

Referred Links:

http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/

https://staticallytyped.wordpress.com/tag/layer-list-level-list-android-custom-views-resources/

http://iserveandroid.blogspot.in/2010/10/progress-bar-implementation-using-level.html

you can download the source code here.

Screenshot here:

custom xml layout

custom xml layout