您的位置:首页 > 其它

仿UC客户端的快速搜索消息通知效果

2016-08-16 14:39 267 查看
仿UC效果:无需权限提示,实现快速搜索悬浮窗

一、效果Gif:

效果说明:点击按钮启动Service 监听剪切板。复制之后,在屏幕顶部显示一个“快速搜索”悬浮窗来显示剪贴板内容。点击悬浮窗后的操作可自定义 / 悬浮窗可自动消失。



二、WindowManager 的使用

通过WindowManager 的使用来构建我们的悬浮窗,设计模式为建造者模式。

/**
* Created by cxm on 2016/8/15.
*/
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;

public class UcNotification {

private static final int DISMISS_INTERVAL = 3000;

private WindowManager mWindowManager;
private WindowManager.LayoutParams mWindowParams;
private View mContentView;
private Context mContext;

// 标记悬浮窗是否显示
private boolean isShowing = false;

// 自定义的监听接口
private OnClickNotificationListener mOnClickNotificationListener;

private TextView mTvContent;

public UcNotification(Builder builder) {

mContext = builder.getContext();

mWindowManager = (WindowManager)
mContext.getSystemService(Context.WINDOW_SERVICE);
mWindowParams = new WindowManager.LayoutParams();

//设置窗口类型
mWindowParams.type = WindowManager.LayoutParams.TYPE_TOAST;// 系统提示window

mWindowParams.gravity = Gravity.LEFT | Gravity.TOP;
mWindowParams.width = WindowManager.LayoutParams.MATCH_PARENT;
mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

mWindowParams.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;

mWindowParams.alpha = 0.95f;

//设置进入和退出动画
mWindowParams.windowAnimations = R.style.NotificationAnim;

//设置窗口起点位置
mWindowParams.x = 0;
mWindowParams.y = 0;

setContentView(mContext, builder);

}

private static final int HIDE_WINDOW = 0;

private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case HIDE_WINDOW:
dismiss();
break;
}
return true;
}
});

/***
* 设置内容视图
*
* @param context
*/
private void setContentView(Context context, Builder builder) {

mContentView = LayoutInflater.from(context).inflate(R.layout.layout_notification, null);

mTvContent = (TextView) mContentView.findViewById(R.id.tv_content);

//取出builder中的内容

setOnClickNotificationListener(builder.listener);
setContent(builder.content);

mContentView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mOnClickNotificationListener.onClickThenDismiss(mTvContent.getText().toString());
dismiss();
}
});
}

private void setOnClickNotificationListener(OnClickNotificationListener listener) {

mOnClickNotificationListener = listener;

}

public void show() {
if (!isShowing) {
isShowing = true;
mWindowManager.addView(mContentView, mWindowParams);
autoDismiss();
}
}

public void dismiss() {
if (isShowing) {
resetState();
mWindowManager.removeView(mContentView);
}
}

/**
* 重置状态
*/
private void resetState() {
isShowing = false;
}

/**
* 自动隐藏通知
*/
private void autoDismiss() {
mHandler.removeMessages(HIDE_WINDOW);
mHandler.sendEmptyMessageDelayed(HIDE_WINDOW, DISMISS_INTERVAL);
}

public void setContent(String content) {
mTvContent.setText(content);
}

@Override
public void onClick(View view) {

Toast.makeText(mContext,"clicked : "+mTvContent.getText().toString(),Toast.LENGTH_SHORT).show();
dismiss();
}

public static class Builder {

private Context context;

private String content = "";

private OnClickNotificationListener listener;

public Context getContext() {
return context;
}

public Builder setContext(Context context) {
this.context = context;
return this;
}

public Builder setOnClickNotificationListener(OnClickNotificationListener listener){
this.listener = listener;
return this;
}

public Builder setContent(String content) {
this.content = content;
return this;
}

public UcNotification build() {

if (null == context)
throw new IllegalArgumentException("The context is Null.");

return new UcNotification(this);
}

}

//悬浮窗点击接口
public interface OnClickNotificationListener {
void onClickThenDismiss(String clipString);
}

}


三、Service 的使用

通过Service的使用来监听剪贴板的变化,这里为了防止onPrimaryClipChanged()的重复多次调用,使用了剪贴板内容字符串的比较判断。

import android.app.Service;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

public class ClipboardService extends Service {

private ClipboardManager clipboardManager;

private String clipString;

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onCreate() {
super.onCreate();
}

@Override
public int onStartCommand(final Intent intent, int flags, int startId) {

if(clipboardManager==null){
clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
}

if (clipString==null){
clipString = "";
}

clipboardManager.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() {
@Override
public void onPrimaryClipChanged() {

CharSequence text = clipboardManager.getPrimaryClip().getItemAt(0).getText();

if(text!=null) {

String s =text.toString();

if (!TextUtils.equals(s, clipString)) {

final UcNotification notification =
new UcNotification.Builder()
.setContext(ClipboardService.this)
.setContent(s)
.setOnClickNotificationListener(new UcNotification.OnClickNotificationListener() {
@Override
public void onClickThenDismiss(String clipString) {
Toast.makeText(ClipboardService.this, "clicked:" + clipString, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(ClipboardService.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

ClipboardService.this.startActivity(intent);
}
}).build();

notification.show();
}
clipString = s;

}

}
});

return Service.START_STICKY;
}

@Override
public void onDestroy() {
super.onDestroy();
}
}


完整项目代码:

UcTopNofitication

参考:

http://www.jianshu.com/p/634cd056b90c
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息