Android samples API Demos之UI篇1(ActionBarCompat-ShareActionProvider)

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>
里面有不少英语,我这蹩脚的水平就不翻译了。
最后来一张效果截图:




要将 Theia 的 api-samples 抽离出来成为一个 npm 包,您可以按照以下步骤操作: 1. 创建一个新的 npm 包,可以使用以下命令: ``` mkdir theia-api-samples && cd theia-api-samples npm init ``` 2. 在新的 npm 包中创建一个名为 `theia-extension` 的文件夹。 3. 将 Theia 项目中的 `theia-samples/api-samples` 目录复制到 `theia-extension` 文件夹中。 4. 在 `theia-extension` 文件夹中创建一个 `package.json` 文件,并添加以下代码: ``` { "name": "@your-scope/theia-api-samples", "version": "1.0.0", "description": "API samples for Theia IDE", "main": "lib/index.js", "license": "MIT", "dependencies": { "@theia/core": "latest", "@theia/filesystem": "latest", "@theia/workspace": "latest" } } ``` 注意,在 `dependencies` 中添加了 `@theia/core`、`@theia/filesystem` 和 `@theia/workspace` 依赖项,这些依赖项是 api-samples 所需的。 5. 在 `theia-extension` 文件夹中创建一个 `tsconfig.json` 文件,并添加以下代码: ``` { "compilerOptions": { "module": "commonjs", "target": "es6", "lib": ["es6", "dom"], "declaration": true, "outDir": "lib" }, "include": ["src/**/*"], "exclude": ["node_modules", "**/*.test.ts"] } ``` 6. 在 `theia-extension` 文件夹中创建一个 `src` 文件夹,并在其中创建一个 `index.ts` 文件,并添加以下代码: ``` import { ContainerModule } from '@theia/core/lib/common'; import { FilesystemSample } from './filesystem-sample'; import { WorkspaceSample } from './workspace-sample'; export default new ContainerModule(bind => { bind(FilesystemSample).toSelf(); bind(WorkspaceSample).toSelf(); }); ``` 这将导出一个 `ContainerModule`,其中包含 `FilesystemSample` 和 `WorkspaceSample`。 7. 在 `theia-extension` 文件夹中创建一个 `filesystem-sample.ts` 文件,并添加以下代码: ``` import { injectable } from 'inversify'; import { UriAwareCommandHandler } from '@theia/core/lib/common/uri-command-handler'; import { Command } from '@theia/core/lib/common/command'; import { FileSystem } from '@theia/filesystem/lib/common/filesystem'; import URI from '@theia/core/lib/common/uri'; @injectable() export class FilesystemSample implements UriAwareCommandHandler { readonly id = 'filesystem-sample'; execute(uri: string): void { const fileSystem = new FileSystem(new URI(uri)); fileSystem.readFile('/example.txt').then(content => console.log(`Content of example.txt is: ${content}`) ); } isEnabled(uri: string): boolean { return true; } readonly command: Command = { id: this.id, label: 'Filesystem Sample' }; } ``` 这将创建一个 `FilesystemSample` 类,该类读取文件系统中的 `/example.txt` 文件,并在控制台中输出其内容。 8. 在 `theia-extension` 文件夹中创建一个 `workspace-sample.ts` 文件,并添加以下代码: ``` import { injectable } from 'inversify'; import { UriAwareCommandHandler } from '@theia/core/lib/common/uri-command-handler'; import { Command } from '@theia/core/lib/common/command'; import { Workspace } from '@theia/workspace/lib/browser/workspace-service'; import URI from '@theia/core/lib/common/uri'; @injectable() export class WorkspaceSample implements UriAwareCommandHandler { readonly id = 'workspace-sample'; execute(uri: string): void { const workspace = new Workspace(new URI(uri)); workspace.getRoot().then(root => console.log(`Workspace root is: ${root.uri}`) ); } isEnabled(uri: string): boolean { return true; } readonly command: Command = { id: this.id, label: 'Workspace Sample' }; } ``` 这将创建一个 `WorkspaceSample` 类,该类获取工作区的根目录,并在控制台中输出其 URI。 9. 在 `theia-extension` 文件夹中创建一个 `index.ts` 文件,并添加以下代码: ``` export * from './filesystem-sample'; export * from './workspace-sample'; export * from './container'; ``` 这将导出 `FilesystemSample`、`WorkspaceSample` 和 `ContainerModule`。 10. 在根目录中创建一个 `.npmignore` 文件,并添加以下代码: ``` # Ignore development files .vscode/ src/ test/ tsconfig.json tslint.json ``` 这将忽略开发文件,以减小 npm 包的大小。 11. 在根目录中创建一个 `.gitignore` 文件,并添加以下代码: ``` # Ignore development files .vscode/ src/ test/ tsconfig.json tslint.json # Ignore build output node_modules/ lib/ ``` 这将忽略开发文件和构建输出。 12. 使用以下命令在本地进行测试: ``` yarn yarn build ``` 13. 使用以下命令将包发布到 npm: ``` npm login npm publish --access=public ``` 这将将包发布到公共的 npm registry 中。 现在,您已经成功地将 Theia 的 api-samples 抽离出来成为一个 npm 包。其他开发人员可以使用 `npm install @your-scope/theia-api-samples` 命令安装并使用这个包。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值