編輯:關於Android編程
現在很多的應用基本都會集成分享這個功能,該功能包括系統分享(比如郵件,短信)和第三方分享(比如QQ和微信)。其中有些公司會選擇使用第三方的庫來簡化這些操作,加快開發,用的比較多的比如友盟社會化分享SDK,缺點就是自由度太低,因為可能你僅僅只是需要QQ和微信,其他的公司就會選擇自己導入所需要的第三方SDK來自定義分享功能,自由度高,於是這篇博客主要來介紹後一種自定義分享功能的案例demo,下圖是demo的運行效果:
具體分析一下源碼,由於分享的內容根據需求的不同而不同,為了簡單起見,我們就以最常用的圖文+鏈接的形式為例,其他情況何以根據需求修改相關類。第一步定義分享的實體類:
ShareModel.java<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">
public class ShareModel {
/** 分享的類型,圖片,文字等 */
public int type;
/** 分享的標題 */
public String title;
/** 分享內容 */
public String content;
/** 分享的鏈接 */
public String shareUrl;
/** 分享圖片的網絡url */
public ArrayList
這個類定義了分享的基本數據類型(按照需求修改該類即可,比如可以添加視頻語音之類)。接著我們建立各自的分享模塊用來區分不同的分享(這裡以系統和QQ分享為例),並且每個分享模塊都要繼承自同一個接口IShare:
IShare.java
public interface IShare {
/**
* @param model 調用分享的實體
* @param context 上下文
* @param type 調用該分享的類別
* @param callback 分享回調
*/
void doShare(ShareModel model, Context context, int type, IShareCallback callback);
/**
* 該函數在{@link android.app.Activity#onActivityResult(int, int, Intent)}
* 調用,用來處理分享的回調,比如QQ和系統分享(微信這種不需要在onActivityResult中處理的直接返回false即可)
* @return 是否為該分享的回調
*/
boolean doShareCallback(int requestCode, int resultCode, Intent data);
}
該接口定義了兩個函數,一個是分享函數,另一個是分享的回調函數,系統分享和QQ分享的相關類繼承該接口實現這兩個函數:
QQ分享TencentShare .class
public class TencentShare implements IShare {
@Override
public void doShare(ShareModel model, Context context, int type, IShareCallback callback) {
//具體看源碼
}
@Override
public boolean doShareCallback(int requestCode, int resultCode, Intent data) {
//具體看源碼
}
}
系統分享SystemShare.class
public class SystemShare implements IShare {
@Override
public void doShare(ShareModel model, Context context, int type, IShareCallback callback) {
//具體看源碼
}
@Override
public boolean doShareCallback(int requestCode, int resultCode, Intent data) {
//具體看源碼
}
}
如果需要集成其他第三方分享,新建相關類實現相關函數即可。然後就是最重要的管理類了,看看該類的源碼:
public class ShareManager {
private Activity activity;
private IShareCallback callback;
private PopupWindow popupWindow;
/** 最新一次調用分享的對象 */
private IShare shareObject;
/**
* @param callback 分享出去的回調
*/
public ShareManager(Activity activity, IShareCallback callback){
this.activity = activity;
this.callback = callback;
//初始化Share枚舉類
Share demo = Share.QQ_FRIEND;
}
/**
* 用來展示分享popUpWindow
* @param model 分享出去的實體
*/
public void show(final ShareModel model) {
if (popupWindow == null) {
popupWindow = new ShareGridViewPopupWindow(activity, new ShareGridViewPopupWindow.IShareClickCallback() {
@Override
public void onShareCallback(int position) {
try {
Class clazz = Share.values()[position].getShareClass();
shareObject = clazz.newInstance();
shareObject.doShare(model, activity, Share.values()[position].getType(), callback);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
});
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
popupWindow = null;
}
});
}
popupWindow.showAtLocation(activity.getWindow().getDecorView(), Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
}
/**
* 用來在activity的onActivityResult函數中注冊分享回調,比如QQ和系統分享
* @return 是否是分享回調,如果是,返回true,表明activity不用處理相關result
*/
public boolean registerOnActivityCallback(int requestCode, int resultCode, Intent data){
return shareObject!=null && shareObject.doShareCallback(requestCode, resultCode, data);
}
/**
* 在此處動態添加分享模塊
*/
public enum Share {
QQ_FRIEND("QQ", R.mipmap.logo_qq, 0, TencentShare.class),
QQ_ZONE("QQ空間", R.mipmap.logo_qzone, 1, TencentShare.class),
MAIL("郵件", R.mipmap.logo_email, 0, SystemShare.class),
MESSAGE("信息", R.mipmap.logo_shortmessage, 1, SystemShare.class);
private String name;
private int drawable;
private Class shareClass;
private int type;
Share(String name, int drawable, int type, Class shareClass){
this.name = name;
this.drawable = drawable;
this.type = type;
this.shareClass = shareClass;
}
public String getName(){
return name;
}
public int getDrawableId(){
return drawable;
}
public int getType(){
return type;
}
public Class getShareClass() {
return shareClass;
}
}
}
該類使用一個enum來集中定義所有的分享,每個分享都會有一個名字和圖片用來展示,而點擊效果的回調則是由相關繼承自IShare接口的class類對象調用doShare函數來進行處理,這麼做的好處是利於管理和以後的分享類別的增加和刪除。該類中還有一個registerOnActivityCallback函數,該函數是用來在Activity中的onActivityResult中注冊分享回調,通知相關分享的回調成功與否。
我們在這裡使用popupWindow來彈出分享框,於是需要自定義一個popupWindow:
ShareGridViewPopupWindow.java類:
public class ShareGridViewPopupWindow extends PopupWindow {
private View mMenuView;
private LayoutInflater inflater;
private GridView gridView;
private TextView tv_dismiss;
private Activity context;
private View view;
public ShareGridViewPopupWindow(Activity context, final IShareClickCallback callback) {
super();
this.context = context;
inflater = (LayoutInflater) context.getSystemService(Service.LAYOUT_INFLATER_SERVICE);
mMenuView = inflater.inflate(R.layout.share_popupwindow, null);
gridView = (GridView) mMenuView.findViewById(R.id.gridview);
tv_dismiss = (TextView) mMenuView.findViewById(R.id.tv_dismiss);
gridView.setAdapter(new GridViewAdapter());
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
if (callback != null)
callback.onShareCallback(position);
dismiss();
}
});
this.setAnimationStyle(R.style.share_PopupAnimation);
//http://stackoverflow.com/questions/3121232/android-popup-window-dismissal
this.setBackgroundDrawable(new BitmapDrawable(null,""));
this.setFocusable(true);
tv_dismiss.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
this.setContentView(mMenuView);
this.setWidth(LayoutParams.MATCH_PARENT);
this.setHeight(LayoutParams.WRAP_CONTENT);
//點擊popUpWindow其他部分消失
mMenuView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
int height = mMenuView.findViewById(R.id.pop_layout).getTop();
int y = (int) event.getY();
if (event.getAction() == MotionEvent.ACTION_UP) {
if (y < height) {
dismiss();
}
}
return true;
}
});
//增加popUpWindow其他部分的灰色效果
view = new View(context);
view.setBackgroundColor(Color.parseColor("#b0000000"));
((ViewGroup)context.getWindow().getDecorView().getRootView()).addView(view);
}
private class GridViewAdapter extends BaseAdapter {
@Override
public int getCount() {
return ShareManager.Share.values().length;
}
@Override
public Object getItem(int position) {
return ShareManager.Share.values()[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.share_grid_item, null);
}
convertView.findViewById(R.id.iv_image).setBackgroundResource(ShareManager.Share.values()[position].getDrawableId());
((TextView)convertView.findViewById(R.id.tv_text)).setText(ShareManager.Share.values()[position].getName());
return convertView;
}
}
@Override
public void dismiss() {
super.dismiss();
((ViewGroup)context.getWindow().getDecorView().getRootView()).removeView(view);
}
public interface IShareClickCallback {
void onShareCallback(int position);
}
}
該popupWindow使用gridView來進行布局,大家可以根據需求修改該布局,關於popupWindow的使用我這裡說幾點:第一點是popupWindow點擊外部和返回鍵消失的處理,點擊外部消失需要使用setOnTouchListener函數來監控用戶觸摸的位置,按下返回鍵的處理需要先使用setBackgroundDrawable函數給該popupWindow設置一個背景,接著使用setFocusable函數設置焦點;第二點是外側的灰色背景,我這裡使用的是當popupWindow展示的時候在decorView上加入一個透明黑色的view,在dismiss的時候去掉,這樣效果就達到了。
從前面Android編譯系統環境初始化過程分析這篇文章可以知道,lunch命令其實是定義在build/envsetup.sh文件中的函數lunch提供的。與
1.什麼是Sqlite? SQLite是輕量級的、嵌入式的、關系型數據庫. 2.Sqlite儲存在Android系統的哪? 數據庫存儲的位置在data/data
在AS裡面新建一個項目之前都一直新建好倉庫用命令行提交的 現在用AS提交不用命令行第一步:在git新建一個倉庫第二步:復制URL第三步:點擊VCS如圖中的選項第四步:在下
activity類 package com.kane.listview; import java.util.ArrayList; import java.util.D