Android ActionBarCompat-ShareActionProvider Sample
This sample shows you how a provide a context-sensitive ShareActionProvider with ActionBarCompat, backwards compatible to API v7.
本示例演示如何为ActionBarCompat提供上下文相关的 ShareActionProvider ,向下兼容API v7 。
项目下载地址:http://download.csdn.net/detail/a599231042/9130907
真是无语了,O__O "…android 的6.0模拟器实在太坑人了,为了看一下这个项目的效果硬是折腾了我老半天,首先是系统浏览器不能够下载东西,一点击下载就崩溃,然后如果浏览器共享位置信息的话,就无限重启。没办法下载,我就复制了一个文件进来,没想到还不能点击安装,因为没有文件关联,无奈之下,只好用adb命名安装了。
关于ActionBar,我发现有一篇不错的博文,大家可以直接去看看:http://blog.csdn.net/yuxlong2010/article/details/9299507
MainActivity类源码:
package com.example.android.actionbarcompat.shareactionprovider;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.ShareActionProvider;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.android.actionbarcompat.shareactionprovider.content.ContentItem;
import java.util.ArrayList;
public class MainActivity extends ActionBarActivity {
// The items to be displayed in the ViewPager
private final ArrayList<ContentItem> mItems = getSampleContent();
// Keep reference to the ShareActionProvider from the menu
private ShareActionProvider mShareActionProvider;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set content view (which contains a CheeseListFragment)
setContentView(R.layout.sample_main);
// Retrieve the ViewPager from the content view
ViewPager vp = (ViewPager) findViewById(R.id.viewpager);
// Set an OnPageChangeListener so we are notified when a new item is selected 设置监听事件
vp.setOnPageChangeListener(mOnPageChangeListener);
// Finally set the adapter so the ViewPager can display items 绑定Adapter
vp.setAdapter(mPagerAdapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
// Retrieve the share menu item
MenuItem shareItem = menu.findItem(R.id.menu_share);
// Now get the ShareActionProvider from the item获取<span style="font-family: Arial, Helvetica, sans-serif;">ShareActionProvider</span>
mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareItem);
// Get the ViewPager's current item position and set its ShareIntent.
int currentViewPagerItem = ((ViewPager) findViewById(R.id.viewpager)).getCurrentItem();
setShareIntent(currentViewPagerItem);
return super.onCreateOptionsMenu(menu);
}
/**
* A PagerAdapter which instantiates views based on the ContentItem's content type.
*/
private final PagerAdapter mPagerAdapter = new PagerAdapter() {
LayoutInflater mInflater;
@Override
public int getCount() {
return mItems.size();
}
@Override
public boolean isViewFromObject(View view, Object o) {
return view == o;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// Just remove the view from the ViewPager
container.removeView((View) object);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// Ensure that the LayoutInflater is instantiated
if (mInflater == null) {
mInflater = LayoutInflater.from(MainActivity.this);
}
// Get the item for the requested position
final ContentItem item = mItems.get(position);
// The view we need to inflate changes based on the type of content
switch (item.contentType) {
case ContentItem.CONTENT_TYPE_TEXT: {
// Inflate item layout for text
TextView tv = (TextView) mInflater
.inflate(R.layout.item_text, container, false);
// Set text content using it's resource id
tv.setText(item.contentResourceId);
// Add the view to the ViewPager
container.addView(tv);
return tv;
}
case ContentItem.CONTENT_TYPE_IMAGE: {
// Inflate item layout for images
ImageView iv = (ImageView) mInflater
.inflate(R.layout.item_image, container, false);
// Load the image from it's content URI
iv.setImageURI(item.getContentUri());
// Add the view to the ViewPager
container.addView(iv);
return iv;
}
}
return null;
}
};
private void setShareIntent(int position) {
if (mShareActionProvider != null) {
// Get the currently selected item, and retrieve it's share intent
ContentItem item = mItems.get(position);
Intent shareIntent = item.getShareIntent(MainActivity.this);
// Now update the ShareActionProvider with the new share intent
mShareActionProvider.setShareIntent(shareIntent);
}
}
/**
* A OnPageChangeListener used to update the ShareActionProvider's share intent when a new item
* is selected in the ViewPager.
*/
private final ViewPager.OnPageChangeListener mOnPageChangeListener
= new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// NO-OP
}
@Override
public void onPageSelected(int position) {
setShareIntent(position);
}
@Override
public void onPageScrollStateChanged(int state) {
// NO-OP
}
};
/**
* @return An ArrayList of ContentItem's to be displayed in this sample
*/
static ArrayList<ContentItem> getSampleContent() {
ArrayList<ContentItem> items = new ArrayList<ContentItem>();
items.add(new ContentItem(ContentItem.CONTENT_TYPE_IMAGE, "photo_1.jpg"));
items.add(new ContentItem(ContentItem.CONTENT_TYPE_TEXT, R.string.quote_1));
items.add(new ContentItem(ContentItem.CONTENT_TYPE_TEXT, R.string.quote_2));
items.add(new ContentItem(ContentItem.CONTENT_TYPE_IMAGE, "photo_2.jpg"));
items.add(new ContentItem(ContentItem.CONTENT_TYPE_TEXT, R.string.quote_3));
items.add(new ContentItem(ContentItem.CONTENT_TYPE_IMAGE, "photo_3.jpg"));
return items;
}
}
这里没有难点,主要是对android的MVC模式要有了解,ViewPager + PagerAdapter
ContentItem 类源码:
package com.example.android.actionbarcompat.shareactionprovider.content;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
/**
* This class encapsulates a content item. Referencing the content's type, and the differing way
* to reference the content (asset URI or resource id).
*/
public class ContentItem {
// Used to signify an image content type
public static final int CONTENT_TYPE_IMAGE = 0;
// Used to signify a text/string content type
public static final int CONTENT_TYPE_TEXT = 1;
public final int contentType;
public final int contentResourceId;
public final String contentAssetFilePath;
public ContentItem(int type, int resourceId) {
contentType = type;
contentResourceId = resourceId;
contentAssetFilePath = null;
}
public ContentItem(int type, String assetFilePath) {
contentType = type;
contentAssetFilePath = assetFilePath;
contentResourceId = 0;
}
public Uri getContentUri() {
if (!TextUtils.isEmpty(contentAssetFilePath)) {
// If this content has an asset, then return a AssetProvider Uri
return Uri.parse("content://" + AssetProvider.CONTENT_URI + "/" + contentAssetFilePath);
} else {
return null;
}
}
//根据类型来获取是文字还是数据流,用于设置Intent
public Intent getShareIntent(Context context) {
Intent intent = new Intent(Intent.ACTION_SEND);
switch (contentType) {
case CONTENT_TYPE_IMAGE:
intent.setType("image/jpg");
// Bundle the asset content uri as the EXTRA_STREAM uri
intent.putExtra(Intent.EXTRA_STREAM, getContentUri());
break;
case CONTENT_TYPE_TEXT:
intent.setType("text/plain");
// Get the string resource and bundle it as an intent extra
intent.putExtra(Intent.EXTRA_TEXT, context.getString(contentResourceId));
break;
}
return intent;
}
}
AssetProvider类源码+xml说明:
<provider android:name=".content.AssetProvider" android:authorities="com.example.android.actionbarcompat.shareactionprovider" android:grantUriPermissions="true"<!--如果 Content Provider 的 grantUriPermissions 属性值为“true”,则该 Provider 内所有的数据都能被授权访问。 可它如果设为“false”,则只有本元素指定的数据子集才能被授权。--> android:exported="true" <!--这个属性用于指示该服务是否能够被其他应用程序组件调用或跟它交互。--> />
package com.example.android.actionbarcompat.shareactionprovider.content;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* A simple ContentProvider which can serve files from this application's assets. The majority of
* functionality is in {@link #openAssetFile(android.net.Uri, String)}.
*/
public class AssetProvider extends ContentProvider {
public static String CONTENT_URI = "com.example.android.actionbarcompat.shareactionprovider";
@Override
public boolean onCreate() {
return true;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// Do not support delete requests.
return 0;
}
@Override
public String getType(Uri uri) {
// Do not support returning the data type
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// Do not support insert requests.
return null;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
// Do not support query requests.
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
// Do not support update requests.
return 0;
}
@Override //主要的就是这个函数了,才使得外面获取数据流
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
// The asset file name should be the last path segment获取文件名
final String assetName = uri.getLastPathSegment();
// If the given asset name is empty, throw an exception
if (TextUtils.isEmpty(assetName)) {
throw new FileNotFoundException();
}
try {
// Try and return a file descriptor for the given asset name
AssetManager am = getContext().getAssets();
return am.openFd(assetName);
} catch (IOException e) {
e.printStackTrace();
return super.openAssetFile(uri, mode);
}
}
}
菜单xml资源:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:support="http://schemas.android.com/apk/res-auto">
<!--
To use ShareActionProvider provided by ActionBarCompat, we reference the class by set the
support:actionProviderClass attribute with the full class name of ShareActionProvider.
-->
<item
android:id="@+id/menu_share"
android:title="@string/menu_share"
support:actionProviderClass="android.support.v7.widget.ShareActionProvider"
support:showAsAction="always" />
</menu>
里面有不少英语,我这蹩脚的水平就不翻译了。
最后来一张效果截图: