Pages

Tuesday 11 March 2014

Collection widget with event handling in android

Hello Friends,

Here we are going to learn how to create Collection widget with each item click event in android.

Final output :



What we required for widget ?


Widget Provider (xml and receiver)
XML stores widget information and reciver update that widget details.

Widget RemoteView service
Remote View (ListView collection) update service which will call RemoteViewFactory.

Widget RemoteViewFactory
RemoteViewFactory used for setting data in listview or gridview, also handling each item getView and its event.


Widget Provider (xml and receiver)

You need to create one xml folder in your res directory and create one file named widget_provider.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/widget_provider_layout"
    android:minHeight="100dip"
    android:minResizeHeight="100dip"
    android:minResizeWidth="100dip"
    android:minWidth="100dip"
    android:previewImage="@drawable/ic_launcher"
    android:resizeMode="vertical|horizontal"
    android:updatePeriodMillis="1800000"
    android:widgetCategory="keyguard|home_screen" >

</appwidget-provider>

You can find more detail about this xml metadata on http://developer.android.com/guide/topics/appwidgets/index.html#MetaData

Note that here I have created widget_provider_layout.xml file as below.


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="@dimen/widget_margin" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#88ffffff" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="Hello Widget"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textColor="#fff"
            android:textStyle="bold" />
    </LinearLayout>

</FrameLayout>

WidgetProvider class:

Now we required one widget provider class (also called widget receiver)


package com.dharmangsoni.widgets;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;

public class WidgetProvider extends AppWidgetProvider {

 @Override
 public void onReceive(Context context, Intent intent) {
  super.onReceive(context, intent);
 }

 @Override
 public void onUpdate(Context context, AppWidgetManager appWidgetManager,
   int[] appWidgetIds) {
  super.onUpdate(context, appWidgetManager, appWidgetIds);
 }
}

Now we are going to register this provider to AndroidManifest.xml so we can see the output of widget.


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

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.dharmangsoni.collectionwidget.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <!-- Widget Receiver -->
        <receiver android:name="com.dharmangsoni.widgets.WidgetProvider" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/widget_provider" />
        </receiver>

    </application>

</manifest>


Now we are ready to see the output of widget. Run application and add widget from widget menu:


Ok now we are going to create our required layout for widget as below:


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="@dimen/widget_margin" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#bbDEDFDE"
        android:orientation="vertical" >

        <LinearLayout
            android:id="@+id/widgetLayoutMain"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#aaDEDFDE"
            android:orientation="horizontal"
            android:paddingLeft="5dp"
            android:paddingRight="5dp" >

            <ImageView
                android:id="@+id/widgetImgLauncher"
                android:layout_width="32dp"
                android:layout_height="32dp"
                android:layout_gravity="center_vertical"
                android:src="@drawable/ic_launcher" />

            <LinearLayout
                android:id="@+id/widgetTopBar"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="vertical"
                android:paddingBottom="4dp"
                android:paddingLeft="8dp"
                android:paddingTop="4dp" >

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@string/app_name"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:textColor="#4B4B4D"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/txvWidgetTitle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="dharmangsoni.blogspot.in"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:textColor="#4B4B4D" />
            </LinearLayout>
        </LinearLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#aaa" />

        <ListView
            android:id="@+id/widgetCollectionList"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
        </ListView>
    </LinearLayout>

</FrameLayout>

Output will be :




Now we are ready with our receiver and xml provider and layout file.

Before create RemoteViewService we have to create RemoteViewFactory for handling listview data.

Widget RemoteViewFactory:

package com.dharmangsoni.widgets;

import java.util.ArrayList;
import java.util.List;

import android.annotation.SuppressLint;
import android.content.Context;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService.RemoteViewsFactory;

@SuppressLint("NewApi")
public class WidgetDataProvider implements RemoteViewsFactory {

 List mCollections = new ArrayList();

 Context mContext = null;

 public WidgetDataProvider(Context context, Intent intent) {
  mContext = context;
 }

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

 @Override
 public long getItemId(int position) {
  return position;
 }

 @Override
 public RemoteViews getLoadingView() {
  return null;
 }

 @Override
 public RemoteViews getViewAt(int position) {
  RemoteViews mView = new RemoteViews(mContext.getPackageName(),
    android.R.layout.simple_list_item_1);
  mView.setTextViewText(android.R.id.text1, mCollections.get(position));
                mView.setTextColor(android.R.id.text1, Color.BLACK);
  return mView;
 }

 @Override
 public int getViewTypeCount() {
  return 1;
 }

 @Override
 public boolean hasStableIds() {
  return true;
 }

 @Override
 public void onCreate() {
  initData();
 }

 @Override
 public void onDataSetChanged() {
  initData();
 }

 private void initData() {
  mCollections.clear();
  for (int i = 1; i <= 10; i++) {
   mCollections.add("ListView item " + i);
  }
 }

 @Override
 public void onDestroy() {

 }

}

Creating RemoteViewService :


package com.dharmangsoni.widgets;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.widget.RemoteViewsService;

@SuppressLint("NewApi")
public class WidgetService extends RemoteViewsService {

 @Override
 public RemoteViewsFactory onGetViewFactory(Intent intent) {

  WidgetDataProvider dataProvider = new WidgetDataProvider(
    getApplicationContext(), intent);
  return dataProvider;
 }

}

Adding service entry into Manifest file under <application> tag:
<!-- Widget service -->
        <service
            android:name="com.dharmangsoni.widgets.WidgetService"
            android:permission="android.permission.BIND_REMOTEVIEWS" />


Updating WidgetProvider to initialize collection view.


package com.dharmangsoni.widgets;

import android.annotation.SuppressLint;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.widget.RemoteViews;

import com.dharmangsoni.collectionwidget.R;

public class WidgetProvider extends AppWidgetProvider {

 @Override
 public void onReceive(Context context, Intent intent) {
  super.onReceive(context, intent);
 }

 @Override
 public void onUpdate(Context context, AppWidgetManager appWidgetManager,
   int[] appWidgetIds) {
  for (int widgetId : appWidgetIds) {
   RemoteViews mView = initViews(context, appWidgetManager, widgetId);
   appWidgetManager.updateAppWidget(widgetId, mView);
  }

  super.onUpdate(context, appWidgetManager, appWidgetIds);
 }


 @SuppressWarnings("deprecation")
 @SuppressLint("NewApi")
 private RemoteViews initViews(Context context,
   AppWidgetManager widgetManager, int widgetId) {

  RemoteViews mView = new RemoteViews(context.getPackageName(),
    R.layout.widget_provider_layout);

  Intent intent = new Intent(context, WidgetService.class);
  intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);

  intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
  mView.setRemoteAdapter(widgetId, R.id.widgetCollectionList, intent);

  return mView;
 }

}

Now run your app will give you following output:




Now adding each item click event for collection and making toast for an item.

To do we have to add setOnClickFillInIntent in getViewAt in WedgetDataProvider.


. . . 
@Override
 public RemoteViews getViewAt(int position) {
  RemoteViews mView = new RemoteViews(mContext.getPackageName(),
    android.R.layout.simple_list_item_1);
  mView.setTextViewText(android.R.id.text1, mCollections.get(position));
  mView.setTextColor(android.R.id.text1, Color.BLACK);
  
  final Intent fillInIntent = new Intent();
  fillInIntent.setAction(WidgetProvider.ACTION_TOAST);
  final Bundle bundle = new Bundle();
  bundle.putString(WidgetProvider.EXTRA_STRING,
    mCollections.get(position));
  fillInIntent.putExtras(bundle);
  mView.setOnClickFillInIntent(android.R.id.text1, fillInIntent);
  return mView;
 }
. . . 


Now handling click event in WidgetProvider->onReceive:


. . . . 
public class WidgetProvider extends AppWidgetProvider {

 public static final String ACTION_TOAST = "com.dharmangsoni.widgets.ACTION_TOAST";
 public static final String EXTRA_STRING = "com.dharmangsoni.widgets.EXTRA_STRING";

 @Override
 public void onReceive(Context context, Intent intent) {
  if (intent.getAction().equals(ACTION_TOAST)) {
   String item = intent.getExtras().getString(EXTRA_STRING);
   Toast.makeText(context, item, Toast.LENGTH_LONG).show();
  }
  super.onReceive(context, intent);
 }

        @SuppressLint("NewApi")
 @Override
 public void onUpdate(Context context, AppWidgetManager appWidgetManager,
   int[] appWidgetIds) {
  for (int widgetId : appWidgetIds) {
   RemoteViews mView = initViews(context, appWidgetManager, widgetId);

   // Adding collection list item handler
   final Intent onItemClick = new Intent(context, WidgetProvider.class);
   onItemClick.setAction(ACTION_TOAST);
   onItemClick.setData(Uri.parse(onItemClick
     .toUri(Intent.URI_INTENT_SCHEME)));
   final PendingIntent onClickPendingIntent = PendingIntent
     .getBroadcast(context, 0, onItemClick,
       PendingIntent.FLAG_UPDATE_CURRENT);
   mView.setPendingIntentTemplate(R.id.widgetCollectionList,
     onClickPendingIntent);

   appWidgetManager.updateAppWidget(widgetId, mView);
  }
  super.onUpdate(context, appWidgetManager, appWidgetIds);
 }
. . . 



Download Full source :
https://www.dropbox.com/s/u019v6arbae37oh/CollectionWidget.tar.gz

Hope you like it.

Friday 7 March 2014

Advance Drawer layout with dynamic Fragment loading

Hello Friends,

Here we are going to create advanced drawer with custom layout and dynamic fragment loading on each drawer item click.

To learn how to add simple drawer in Android refer this tutorial:

http://dharmangsoni.blogspot.in/2013/11/simple-navigational-drawer-layout-in.html

What we are going to develop?


What we required?

  • Custom drawer row view
  • Drawer Item handler class
  • Drawer ListView custom adapter to handle each custom row
  • Color selector when user click on drawer item
  • Custom ImageView for handling tint color (image color) when drawer item selected

Creating custom drawer row layout xml file:

Here we required two different layout; one for grouping and second for our row item.

drawer_item_group_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ffffff"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/txvDrawerItemTitle"
        style="?android:attr/textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:paddingBottom="2dp"
        android:paddingLeft="10dp"
        android:paddingTop="10dp"
        android:text="Title"
        android:textAllCaps="true"
        android:textColor="#4B4B4D"
        android:textStyle="bold" />

    <View
        android:id="@+id/viewDrawerGroupView"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#BEBEBE" />

</LinearLayout>

drawer_item_layout.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.dharmangsoni.customdrawer"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/drawer_item_selector"
    android:orientation="horizontal"
    android:weightSum="2" >

    <com.dharmangsoni.drawer.DrawerIconView
        android:id="@+id/imgDrawerItemIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="0dp"
        android:layout_marginTop="8dp"
        android:src="@drawable/ic_action_inbox"
        android:visibility="gone"
        custom:tint="@color/drawer_color_selector" />

    <View
        android:id="@+id/drawerTagColor"
        android:layout_width="5dp"
        android:layout_height="match_parent"
        android:background="#ffffff"
        android:visibility="gone" />

    <TextView
        android:id="@+id/txvDrawerItemTitle"
        style="?android:attr/textAppearanceMedium"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:gravity="center_vertical"
        android:padding="10dp"
        android:text="Title"
        android:textColor="@color/drawer_color_selector" />

    <TextView
        android:id="@+id/txvDrawerItemCounter"
        style="?android:attr/textAppearanceSmall"
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:gravity="center"
        android:padding="10dp"
        android:text="99+"
        android:textColor="@color/drawer_color_selector"
        android:textStyle="bold" />

</LinearLayout>

Here you can see some @color and @drawable resources. We have created our resources to handle each item background and textcolor. For that you need to create following files:

@color

Create new folder in /res/color and create drawer_color_selector.xml


<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_activated="true" android:color="#ffffff"/>
    <item android:color="#4B4B4D"/>

</selector>

@drawable

create new folder in /res/drawable and create following three files:

drawer_item_focused.xml


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <gradient
        android:angle="270"
        android:endColor="#33B5E5"
        android:startColor="#33B5E5" />

</shape>

drawer_item_pressed.xml


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <gradient
        android:angle="270"
        android:endColor="#8bd7f0"
        android:startColor="#8bd7f0" />

</shape>

drawer_item_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/drawer_item_pressed" android:state_activated="false" android:state_pressed="true"/>
    <item android:drawable="@drawable/drawer_item_focused" android:state_activated="true"/>

</selector>

This selector will change row color when you click on the drawer item and with selector when item is selected @color selector will change the content color as per selection of the drawer item.



Now we are ready with our layout (resources xml) 

Now we create our required class files:

1. DrawerItem.java

Drawer item stores each drawer item details. Title, Group info, icon, tag color and also Fragment instance. Here it is,

package com.dharmangsoni.drawer;

import android.support.v4.app.Fragment;
import android.widget.AdapterView.OnItemClickListener;

public class DrawerItem {

 private int id = 0;
 private String title = "";
 private int counter = 0;
 private boolean isGroupTitle = false;
 private int icon = 0;
 private String tagColor = null;
 private Fragment fragment = null;

 public DrawerItem(int id, String title, Fragment fragment, int counter) {
  this.id = id;
  this.title = title;
  this.counter = counter;
  this.fragment = fragment;
 }

 public DrawerItem(int id, String title, Fragment fragment, int counter,
   int icon) {
  this.id = id;
  this.title = title;
  this.counter = counter;
  this.icon = icon;
  this.fragment = fragment;
 }

 public DrawerItem(int id, String title, Fragment fragment, int counter,
   String tagColor) {
  this.id = id;
  this.title = title;
  this.counter = counter;
  this.tagColor = tagColor;
  this.fragment = fragment;
 }

 public DrawerItem(int id, String title, boolean isGroupTitle) {
  this.id = id;
  this.title = title;
  this.isGroupTitle = isGroupTitle;
 }

 public DrawerItem(int id, String title, int counter, boolean isGroupTitle) {
  this.id = id;
  this.title = title;
  this.counter = counter;
  this.isGroupTitle = isGroupTitle;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getTitle() {
  return title;
 }

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

 public int getCounter() {
  return counter;
 }

 public void setCounter(int counter) {
  this.counter = counter;
 }

 public void isGroupTitle(boolean flag) {
  this.isGroupTitle = flag;
 }

 public boolean isGroupTitle() {
  return this.isGroupTitle;
 }

 public void setIcon(int resource) {
  icon = resource;
 }

 public int getIcon() {
  return icon;
 }

 public void setTagColor(String tagColor) {
  this.tagColor = tagColor;
 }

 public String getTagColor() {
  return this.tagColor;
 }

 public Fragment getFragment() {
  return fragment;
 }

 public void setFragment(Fragment fragment) {
  this.fragment = fragment;
 }

 public interface DrawerItemClickListener extends OnItemClickListener {
 }
}

This class contain all getter setters and also some required constructor for setting group, tag color, counter and fragments.

2. DrawerIconView.java

This class contain ImageView but with dynamic tint color changing. ImageView does not support dynamic selector tint color so we have created custom image view for showing icon.

We uses our custom attribute as tint for this ImageView.
To create custom attribute for control create attrs.xml file in /res/values/ and create file named attrs.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="DrawerIconView">
        <attr name="tint" format="reference|color" />
    </declare-styleable>

</resources>

package com.dharmangsoni.drawer;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.ImageView;

import com.dharmangsoni.customdrawer.R;

public class DrawerIconView extends ImageView {
 private ColorStateList tint;

 public DrawerIconView(Context context) {
  super(context);
 }

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

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

 private void init(Context context, AttributeSet attrs, int defStyle) {

  TypedArray a = context.obtainStyledAttributes(attrs,
    R.styleable.DrawerIconView);
  tint = a.getColorStateList(R.styleable.DrawerIconView_tint);
  a.recycle();
 }

 @Override
 protected void drawableStateChanged() {
  super.drawableStateChanged();
  if (tint != null && tint.isStateful()) {
   updateTintColor();
  }
 }

 public void setColorFilter(ColorStateList tint) {
  this.tint = tint;
  super.setColorFilter(tint.getColorForState(getDrawableState(), 0));
 }

 private void updateTintColor() {
  int color = tint.getColorForState(getDrawableState(), 0);
  setColorFilter(color);
 }
}

3. DrawerAdapter.java

The drawer adapter; is responsible for handling each row view and creating custom view as per drawer item requirement.

package com.dharmangsoni.drawer;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import com.dharmangsoni.customdrawer.R;

public class DrawerAdatper extends ArrayAdapter {

 List mObjects = null;
 Context mContext = null;
 int mResource = 0;
 int mGroupResource = 0;

 public DrawerAdatper(Context context, int item_resource,
   int item_group_resource, List objects) {
  super(context, item_resource, objects);
  mObjects = new ArrayList(objects);
  mContext = context;
  mResource = item_resource;
  mGroupResource = item_group_resource;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  View mView = convertView;
  DrawerItem item = mObjects.get(position);
  LayoutInflater inflater = (LayoutInflater) mContext
    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  if (item.isGroupTitle()) {
   mView = inflater.inflate(mGroupResource, parent, false);
  } else {
   mView = inflater.inflate(mResource, parent, false);
  }

  // Setting title
  TextView txvTitle = (TextView) mView
    .findViewById(R.id.txvDrawerItemTitle);
  txvTitle.setText(item.getTitle());

  if (!item.isGroupTitle()) {
   // setting counter
   TextView txvCounter = (TextView) mView
     .findViewById(R.id.txvDrawerItemCounter);
   if (item.getCounter() > 0) {
    String counter_string = (item.getCounter() > 99) ? "99+" : item
      .getCounter() + "";
    txvCounter.setText(counter_string);
   } else {
    txvCounter.setVisibility(View.GONE);
   }

   DrawerIconView imgItemIcon = (DrawerIconView) mView
     .findViewById(R.id.imgDrawerItemIcon);
   if (item.getIcon() != 0) {
    imgItemIcon.setVisibility(View.VISIBLE);
    imgItemIcon.setImageDrawable(mContext.getResources()
      .getDrawable(item.getIcon()));
   }

   View tagColorview = (View) mView.findViewById(R.id.drawerTagColor);
   if (item.getTagColor() != null) {
    tagColorview.setBackgroundColor(Color.parseColor(item
      .getTagColor()));
    tagColorview.setVisibility(View.VISIBLE);
   } else {
    tagColorview.setVisibility(View.GONE);
   }

  }
  return mView;
 }

}

Now we are ready with custom Drawer. We just need to create item list and pass it to custom drawer adapter and just implement our item click listener.

Here I create only one Fragment to handle each item click but pass different position to bundle.

DetailFragment.java


package com.dharmangsoni.customdrawer;

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;

public class DetailFragment extends Fragment {

 View mView = null;

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  mView = inflater.inflate(R.layout.fragment_detail, container, false);

  Bundle bundle = getArguments();
  if (bundle != null) {
   TextView txvDescription = (TextView) mView
     .findViewById(R.id.txvDescription);
   txvDescription.setText(bundle.getString("drawer_title"));

  }

  return mView;
 }
}


fragment_detail.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ffffff"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/txvDescription"
        style="?android:attr/textAppearanceLarge"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Drawer Item Clicked"
        android:textAllCaps="true"
        android:textColor="#4B4B4D"
        android:textStyle="bold" />

</LinearLayout>


Now, it time to create drawer in MainActivity.java


package com.dharmangsoni.customdrawer;

import java.util.ArrayList;
import java.util.List;

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.DrawerLayout;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

import com.dharmangsoni.drawer.DrawerAdatper;
import com.dharmangsoni.drawer.DrawerItem;

public class MainActivity extends FragmentActivity implements
  DrawerItem.DrawerItemClickListener {

 String mTitle = "";
 String mDrawerTitle = "";
 ListView mDrawerList = null;
 DrawerAdatper mAdatper = null;
 DrawerLayout mDrawerLayout = null;
 Integer mDrawerItemSelectedPosition = -1;
 ActionBarDrawerToggle mDrawerToggle = null;
 List mDrawerItems = new ArrayList();

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

  mTitle = getResources().getString(R.string.app_name);
  mDrawerTitle = getResources().getString(R.string.drawer_open);
  mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
  mDrawerList = (ListView) findViewById(R.id.drawer_list);
  mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
    R.drawable.ic_drawer, R.string.drawer_open, R.string.app_name) {

   @Override
   public void onDrawerClosed(View drawerView) {
    super.onDrawerClosed(drawerView);
    setTitle(mTitle);
   }

   @Override
   public void onDrawerOpened(View drawerView) {
    super.onDrawerOpened(drawerView);
    setTitle(mDrawerTitle);
   }

  };
  mDrawerLayout.setDrawerListener(mDrawerToggle);
  getActionBar().setHomeButtonEnabled(true);
  getActionBar().setDisplayHomeAsUpEnabled(true);
  setDrawerItemList();
 }

 private DetailFragment getFragment(String desc) {
  DetailFragment frag = new DetailFragment();
  Bundle bundle = new Bundle();
  bundle.putString("drawer_title", desc);
  frag.setArguments(bundle);
  return frag;
 }

 private void setDrawerItemList() {

  // Messages
  mDrawerItems.add(new DrawerItem(1, "Messages", true));
  mDrawerItems.add(new DrawerItem(2, "Inbox", getFragment("Inbox"), 150,
    R.drawable.ic_action_inbox));
  mDrawerItems.add(new DrawerItem(3, "To: me", getFragment("To: me"), 0,
    R.drawable.ic_action_user));
  mDrawerItems.add(new DrawerItem(4, "To-do", getFragment("To-do"), 0,
    R.drawable.ic_action_todo));
  mDrawerItems.add(new DrawerItem(5, "Archives", getFragment("Archives"),
    0, R.drawable.ic_action_archive));

  // Groups
  mDrawerItems.add(new DrawerItem(6, "My Groups", true));
  mDrawerItems
    .add(new DrawerItem(7, "Join Group", getFragment("Join Group"),
      0, R.drawable.ic_action_social_group));
  mDrawerItems.add(new DrawerItem(8, "R&D", getFragment("R&D"), 0,
    "#218559"));
  mDrawerItems.add(new DrawerItem(9, "HR Policies",
    getFragment("HR Policies"), 5, "#192823"));
  mDrawerItems.add(new DrawerItem(10, "Company News",
    getFragment("Company News"), 0, "#FF8800"));

  // Notes
  mDrawerItems.add(new DrawerItem(11, "Notes", true));
  mDrawerItems.add(new DrawerItem(12, "All Notes",
    getFragment("All Notes"), 5, R.drawable.ic_menu_notes));
  mDrawerItems.add(new DrawerItem(13, "Archives",
    getFragment("Archives"), 0, R.drawable.ic_action_archive));
  mDrawerItems.add(new DrawerItem(14, "New", getFragment("New"), 0,
    "#9933CC"));
  mDrawerItems.add(new DrawerItem(15, "Today", getFragment("Today"), 0,
    "#669900"));
  mDrawerItems.add(new DrawerItem(16, "This Week",
    getFragment("This Week"), 0, "#FF8800"));

 }

 @Override
 public void onStart() {
  super.onStart();
  mAdatper = new DrawerAdatper(this, R.layout.drawer_item_layout,
    R.layout.drawer_item_group_layout, mDrawerItems);
  mDrawerList.setAdapter(mAdatper);
  mDrawerList.setOnItemClickListener(this);
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  if (mDrawerToggle.onOptionsItemSelected(item)) {
   return true;
  }
  return super.onOptionsItemSelected(item);
 }

 @Override
 public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  mDrawerToggle.onConfigurationChanged(newConfig);
 }

 @Override
 protected void onPostCreate(Bundle savedInstanceState) {
  super.onPostCreate(savedInstanceState);
  mDrawerToggle.syncState();
 }

 @Override
 public void onItemClick(AdapterView adapter, View view, int position,
   long id) {
  DrawerItem item = mDrawerItems.get(position);
  if (!item.isGroupTitle()) {
   mDrawerItemSelectedPosition = position;
   Fragment fragment = item.getFragment();
   getSupportFragmentManager().beginTransaction()
     .replace(R.id.frame_container, fragment).commit();
  }
  mDrawerList.setItemChecked(mDrawerItemSelectedPosition, true);
  mDrawerLayout.closeDrawers();
 }
}


In this, setDrawerItemList() will set each drawer item with getFragment() which create fragment instance for each row.

Here is full source code of this application:

https://www.dropbox.com/s/ghnly2861e2au0l/AdvanceDrawer.tar.gz

Enjoy.. :) 

Monday 25 November 2013

Simple Navigational Drawer Layout in Android

Hello Friends,

Today we are going to learn how to create Simple Navigational Drawer Layout in Android application.

Development Level : Intermediate

The Navigational Drawer is part of the suport library v4.

Navigational Drawer looks like below and of course we can modify or create its custom layout as per our requirement.



What is Navigation Drawer and how we can use it ?

The navigation drawer is a panel that transitions in from the left edge of the screen and displays the app’s main navigation options.

Displaying the navigation drawer

The user can bring the navigation drawer onto the screen by swiping from the left edge of the screen or by touching the application icon on the action bar.

As the navigation drawer expands, it overlays the content but not the action bar. When the drawer is fully extended, the action bar adjusts its content by replacing the current action bar title with the app name and removing all actions that are contextual to the view underneath the navigation drawer. The overflow menu with the standard action items for Settings and Help remains visible.

For more detailed article on Navigational Drawer please visit this Official Android Developer Article :
http://developer.android.com/design/patterns/navigation-drawer.html


Ok, Lets start with our application development:

Here we are going to create one simple drawer menu with simple layout which contain Menu title as color name. When we click on any color it will change the background color of our main layout screen.


First, Creating new android application with following detail showed in screenshot:


Click next and complete your new application creation wizard.

We required drawer icon for our action bar to handle drawer. To download drawer icon click below link:


It contains Navigation_Drawer_Indicator  directory.
Copy all the directory from holo_light and paste in our project's res directory.

Now we are ready to create our first drawer menu.

Create a Drawer Layout

To add a navigation drawer, declare your user interface with a DrawerLayout object as the root view of your layout. Inside the DrawerLayout, add one view that contains the main content for the screen (your primary layout when the drawer is hidden) and another view that contains the contents of the navigation drawer.

For Example in our application :
Open activity_main.xml and write following UI code for drawer layout :

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"   
   android:id="@+id/drawer_layout"   
   android:layout_width="match_parent"   
   android:layout_height="match_parent" >   
   <FrameLayout   
    android:id="@+id/frame_container"   
    android:layout_width="match_parent"   
    android:layout_height="match_parent" />   
   <ListView   
    android:id="@+id/drawer_list"   
    android:layout_width="240dp" 
    android:background="#fff"  
    android:layout_height="match_parent"   
    android:layout_gravity="start" />   
  </android.support.v4.widget.DrawerLayout>   

This layout contain DrawerLayout View group:
with one FrameLayout which is our main (primary) layout of different fragments and second one is ListView that is our drawer list view.

This layout demonstrates some important layout characteristics:

  • The main content view (the FrameLayout above) must be the first child in the DrawerLayout because the XML order implies z-ordering and the drawer must be on top of the content.
  • The main content view is set to match the parent view's width and height, because it represents the entire UI when the navigation drawer is hidden.
  • The drawer view (the ListView) must specify its horizontal gravity with the android:layout_gravity attribute. To support right-to-left (RTL) languages, specify the value with "start" instead of "left" (so the drawer appears on the right when the layout is RTL).
  • The drawer view specifies its width in dp units and the height matches the parent view. The drawer width should be no more than 320dp so the user can always see a portion of the main content.
We are ready with our drawer layout now we have to provide list to that drawer. Now we create DrawerLayout object and ListView object to fill data to it.

For that Open your MainActivity.java file and declare objects as below:

 ListView mDrawerList = null;  
 DrawerLayout mDrawerLayout = null;  
 ActionBarDrawerToggle mDrawerToggle = null;  

We create one method init() for Initialize the Drawer List:

private void init() {  
      // Initialize Listview  
      mDrawerList = (ListView) findViewById(R.id.drawer_list);  
      // Initialize drawer layout  
      mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);  
      // creating color string array for our drawer listview  
      String[] data_list = new String[] { "Red", "Oragne", "Blue", "Purple",  
                "Black", "Pink" };  
      // creating adatper for listview  
      ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,  
                android.R.layout.simple_list_item_1, data_list);  
      // providing adapter to listview  
      mDrawerList.setAdapter(adapter);  
 }  

After creating this method we calling it in onCreate method and executing our program.
After successful execution following output will appear.

This is work only if you touch screen left to right. Now we add drawer toggle by clicking on application icon.

For that we create one new method actionbarToggleHandler as below:

 private void actionbarToggleHandler() {  
      getActionBar().setHomeButtonEnabled(true);  
      getActionBar().setDisplayHomeAsUpEnabled(true);  
      mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,  
                R.drawable.ic_drawer, R.string.drawer_open,  
                R.string.drawer_close) {  
           @Override  
           public void onDrawerClosed(View drawerView) {  
                getActionBar().setTitle(mTitle);  
           }  
           @Override  
           public void onDrawerOpened(View drawerView) {  
                getActionBar().setTitle(mDrawerTitle);  
           }  
      };  
      mDrawerLayout.setDrawerListener(mDrawerToggle);  
 } 

This will change the UI of action bar home icon but we are not able to open our drawer with action bar home menu. To enable click event on app icon we have override two methods :

onOptionsItemSelected
Pass the event to ActionBarDrawerToggle, if it returns true, then it has handled the app icon touch event

onPostCreate
Sync the toggle state after onRestoreInstanceState has occurred.

Output Before override method and after override method:

Before : 

After :



We are ready with our simple layout. Now what next ??

Now we provide click event to each list item and change the color of background as item click.

For that we have to provide on Item click listener to ListView.

So, We create one class which implements OnItemClickListener as below:

 class DrawerItemClickListener implements OnItemClickListener {  
      @Override  
      public void onItemClick(AdapterView adapter, View view, int position, long id) {  
      }  
 }  

And than providing click listener to listview in init method:

private void init() {  
      // Initialize Listview  
      mDrawerList = (ListView) findViewById(R.id.drawer_list);  
      // Initialize drawer layout  
      mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);  
      // creating color string array for our drawer listview  
      String[] data_list = new String[] { "Red", "Oragne", "Blue", "Purple",  
                "Black", "Pink" };  
      // creating adatper for listview  
      ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,  
                android.R.layout.simple_list_item_1, data_list);  
      // providing adapter to listview  
      mDrawerList.setAdapter(adapter);  
      mDrawerList.setOnItemClickListener(new DrawerItemClickListener());  
      // Initializing title  
      mTitle = getResources().getString(R.string.app_name);  
      mDrawerTitle = getResources().getString(R.string.drawer_open);  
      actionbarToggleHandler();  
 }  

And providing background color change code to our listener  but before adding code please make our data_list string array global so we can access it from our listener:

 class DrawerItemClickListener implements OnItemClickListener {  
      @Override  
      public void onItemClick(AdapterView adapter, View view, int position,  
           long id) {  
           FrameLayout frameLayout = (FrameLayout) findViewById(R.id.frame_container);  
           frameLayout.setBackgroundColor(Color  
                     .parseColor(data_list[position]));  
      }  
 }  

After adding click event application will run as below output :



Here the drawer is not automatically close when we click on the item. For that we have to close it manually when item selected:

for that just add below code in Itemclick listener:

mDrawerLayout.closeDrawers();


Demo for application :




Download demo application


Hope you like it.

Thank You.

Monday 18 November 2013

Host static HTML website on google drive and access publicly for Free

Hello Friends,

Today when i'm surfing on web got something exciting with Google drive. We can host HTML website with using of Google drive for free.

Let see the example :

https://googledrive.com/host/0B4rYHWlb88LUelAxcjdjWFVOa0U/

Amazing thing is that it can support Javascript as well as JQuery.

Follow the steps to create your own static website and host it on your google drive.

Step 1:

Open your google drive and create one directory with name you want and click on share button as shown in below image:


Step 2:

Click on Change link as shows below:



Step 3 :

Select first option Public on the web



Step 4 :

Be ready with your static website which contains pure HTML, CSS, JavaScript (if any) code and open the directory which you have created and upload all files.

Note that the main file index.html is your default access file.

After completing your upload it's directory structure is something like:

<your directory>/index.html



Now open directory that contain index.html file and copy token from url as shown in below image:





Now your website is ready to public view.

Just paste your token after following link:

http://googledrive.com/host/<your token>

You can access your website now.


Hope you Enjoyed it.

Thank You.

Tuesday 29 October 2013

OpenERP Mobile Beta Testing Version Launched

Hello All,

OpenERP SA launched OpenERP Mobile for Beta Testing.

To become a Tester for OpenERP Mobile follow the steps as given below:

1. Login with your Google account which you are using in your Android device with Play Store

2. Become a member of OpenERP English Community on Google Plus.

3. Open below link in your browser (you can also open it in your android device browser)

https://play.google.com/apps/testing/com.openerp

You can see below page :


Click on BECOME A TESTER

Now you can Install app on your device from Google Play Store by clicking link on page at last.



After successful install of app on your device you can configure app for your OpenERP 7.0 by providing your URL or if you using your server as local than provide your local IP (note that you must have to connect your device with our local network if you are using local OpenERP server)


Than select your database and just login.


If you found any problem or any trace back than report issue with your message.

You can post bugs / problems related to mobile application also on https://bugs.launchpad.net/openerp-mobile

Write Feedback on : mobile@openerp.co.in







OpenERP Mobile by OpenERP SA

OpenERP Mobile is Enterprise Social Client based on Android, enables you to access your OpenERP Wall, Meetings, Notes and Messages from groups, encourage you to updated with companies' current activities for which you are responsible. You can also share messages, notes and schedule meetings through the same application.

Major Features :
  1. Offline Access
  2. Multiple Account Support
  3. Widget for Messages and Notes
  4. Integrated with Address Book and Calendar 
Supported OpenERP Version: OpenERP 7.0

Some screenshots for OpenERP Mobile: