Adding an ActionProvider

In order to use a custom view instead of a simple button in action bar, the ActionProvider class could be the solution. ActionProvider has been available since API Level 14. ActionProvider can generate a custom view in the action bar, can generate submenus, and can handle events of the views that it generates. In order to create an ActionProvider, we should extend the ActionProvider class. The following code shows a sample class that extends the ActionProvider class and displays a custom layout instead of a simple button in action bar:

import android.content.Context;
import android.view.ActionProvider;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;

public class Chapter1ActionProvider extends ActionProvider {

  Context mContext;
  
  public Chapter1ActionProvider(Context context) {
    super(context);
    mContext = context;
  }

  @Override
  public View onCreateActionView() {
        //This method is the place where we generate a custom layout for the Action Bar menu item
     LayoutInflater layoutInflater = LayoutInflater.from(mContext);
         View view = layoutInflater.inflate(R.layout.action_provider, null);
         ImageButton button = (ImageButton) view.findViewById(R.id.button);

         button.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
          Toast.makeText(mContext, "Action Provider click", Toast.LENGTH_LONG).show();
             }
         });
    return view;
  }
  
  @Override
  public boolean onPerformDefaultAction() {
          //This is the method which is called when the Action Bar menu item is in overflow menu and clicked from there
          Toast.makeText(mContext, "Action Provider click", Toast.LENGTH_LONG).show();
    return true;
  }
}

We have to add a constructor and override the onCreateActionView() method. In the constructor, we assign Context to a variable because we are going to need it in further implementations. The onCreateActionView() method is the place where we generate a custom layout for the action bar menu item. onPerformDefaultAction() is the method which is called when the action bar menu item is in the overflow menu and is clicked from there. If the ActionProvider provides submenus, this method is never called. The layout XML for the custom layout used in the onCreateActionView() method is shown in the following code block:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:focusable="true"
    android:addStatesFromChildren="true"
    android:background="?android:attr/actionBarItemBackground"
    style="?android:attr/actionButtonStyle">

    <ImageButton android:id="@+id/button"
        android:background="@drawable/ic_launcher"
        android:layout_width="32dip"
        android:layout_height="32dip"
        android:layout_gravity="center"
        android:scaleType="fitCenter"
        android:adjustViewBounds="true" />
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Some Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

As you can see in the XML file, we added an ImageButton component and a TextView component to a LinearLayout layout. The onClickListener() event of ImageButton is implemented in the onCreateActionView() method of the Chapter1ActionProvider class. In this event, a Toast message is displayed.

The Activity class that displays the action bar is shown the following code block:

public class Chapter1ActionProviderActivity extends Activity{

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
  }
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    return true;
  }
  
   @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    // Handle item selection
    switch (item.getItemId()) {

    case R.id.about:
        Toast.makeText(this, "About options menu button is pressed", Toast.LENGTH_LONG).show();
        return true;
      default:
        return super.onOptionsItemSelected(item);
      }
    }
}

In order to display a custom layout for an action bar menu item, we have to assign an ActionProvider class in the menu XML file. We assign Chapter1ActionProvider which was implemented as in the earlier code as ActionProvider. The menu XML file in our example is as follows:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    
    <item android:id="@+id/settings" android:title="Settings" android:showAsAction="ifRoom|withText"
        
    android:actionProviderClass="com.chapter1.Chapter1ActionProvider"></item>
    
    <item android:id="@+id/about" android:title="About" android:showAsAction="ifRoom|withText"></item>
    
</menu>

As you see in the menu XML file, we provided an ActionProvider class to the settings menu item. The last important thing is setting the minimum SDK version to API Level 14 in the AndroidManifest.xml file, because ActionProvider is a new feature released in API Level 14. The AndroidManifest.xml file should look like the following code block:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.chapter1"
    android:versionCode="1"
    android:versionName="1.0" >
<!—set minSDKversion to 11 because ActionProvider is
     available since API Level 11-->

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

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

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

</manifest>

When you run this application in an emulator, a user interface component with an image button and a text view will be displayed in the action bar. A toast message will be displayed if you press the image button. The screen will look like the following:

Adding an ActionProvider

Adding submenus to the ActionProvider

It is possible to show submenus with ActionProvider. In order to add submenus, we should override the onPrepareSubMenu(SubMenu subMenu) and hasSubMenu() methods in the Chapter1ActionProvider class. The resulting code of the Chapter1ActionProvider class should look like the following code block:

package com.chapter1;

import android.app.Activity;
import android.content.Context;
import android.view.ActionProvider;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.SubMenu;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;

public class Chapter1ActionProvider extends ActionProvider implements 
OnMenuItemClickListener {

  Context mContext;
  
  public Chapter1ActionProvider(Context context) {
    super(context);
    mContext = context;
  }

  @Override
  public View onCreateActionView() {
         return null;
  }
  
  @Override
  public boolean onPerformDefaultAction() {
    
    Toast.makeText(mContext, "Action Provider click", Toast.LENGTH_LONG).show();
    return true;
  }
  
  @Override
  public void onPrepareSubMenu(SubMenu subMenu) {
    //In order to add submenus, we should override this method
    // we dynamically created submenus

    subMenu.clear();
    subMenu.add("SubItem1").setOnMenuItemClickListener(this);
    subMenu.add("SubItem2").setOnMenuItemClickListener(this);
  }

  @Override
  public boolean onMenuItemClick(MenuItem item) {
    
    Toast.makeText(mContext, "Sub Item click", Toast.LENGTH_LONG).show();
    return true;
  }
  
  @Override
  public boolean hasSubMenu() {
       // we implemented it as returning true because we have menu
    return true;
  }

}

In the onPrepareSubMenu(SubMenu subMenu) method, we dynamically created submenus and set their onMenuItemClickListener events. The onPrepareSubMenu(SubMenu subMenu) method is called if the hasSubMenu() method returns true, so we implemented it as returning true.

It is also possible to create submenus from a menu XML file. If you want to create submenus from a menu XML file, onPrepareSubMenu(SubMenu subMenu) should look like the following code block:

  @Override
  public void onPrepareSubMenu(SubMenu subMenu) {

    MenuInflater inflater = ((Activity)mContext).getMenuInflater();
    inflater.inflate(R.menu.menu2, subMenu);
  }

This code shows how we could inflate an XML file to create the submenus using the menu XML file menu2.

ShareActionProvider

ShareActionProvider provides a consistent way of sharing. It puts an action button on the action bar with a share icon. When you click that button, it lists the available applications for sharing. All you need is to declare ShareActionProvider in the menu item as shown in the following code block:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    
    <item android:id="@+id/share" android:title="Share" android:showAsAction="ifRoom"
    android:actionProviderClass="android.widget.ShareActionProvider"></item>
    <item android:id="@+id/about" android:title="About" android:showAsAction="ifRoom"></item>
    <item android:id="@+id/settings" android:title="Settings" android:showAsAction="ifRoom"></item>
    
</menu>

The Activity class that uses ShareActionProvider should look like the following code block:

package com.chapter1;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ShareActionProvider;

public class Chapter1ShareActionProviderActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
      
      ShareActionProvider myShareActionProvider;
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    MenuItem item = menu.findItem(R.id.share);
    myShareActionProvider = (ShareActionProvider)item.getActionProvider();
    myShareActionProvider.setShareHistoryFileName(ShareActionProvider.DEFAULT_SHARE_HISTORY_FILE_NAME);
    myShareActionProvider.setShareIntent(getShareIntent());
    
    return true;
    }
    
    private Intent getShareIntent() {
      Intent shareIntent = new Intent(Intent.ACTION_SEND);
      shareIntent.setType("text/plain");
      shareIntent.putExtra(Intent.EXTRA_TEXT, "www.somesite.com");
      return shareIntent;
      }

}

As you can see in the code, we get the ShareActionProvider attribute of the menu item in the onCreateOptionsMenu(Menu menu) method. Then we define the intent for sharing with the setShareIntent method of ShareActionProvider. getShareIntent() method creates an intent for sharing text. We use this method to define intent for the ShareActionProvider instance.

ShareActionProvider keeps the history of applications used for sharing in a file. The default file that ShareActionProvider uses is ShareActionProvider.DEFAULT_SHARE_HISTORY_FILE_NAME. It is possible to change this file with the setShareHistoryFileName method. All you need is to pass an XML file name with the .xml extension to this method. ShareActionProvider uses this file to find the most frequently used application for sharing. Then it displays the most frequently used application near the share action button as a default sharing target.

The screen of the application with ShareActionProvider looks like the following:

ShareActionProvider

Since the ShareActionProvider was introduced in API Level 14, we have to set the minimum SDK to 14 in the AndroidManifest.xml file as shown in the following code block:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.chapter1"
    android:versionCode="1"
    android:versionName="1.0" >
<!—set minSdkVersion to 14 because ShareActionProvider is available
    since API Level 14-->

    <uses-sdk android:minSdkVersion="14" />

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

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

</manifest>
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
34.231.180.210