您的位置:首页 > 移动开发 > Android开发

always on top button in android

2011-06-09 11:49 357 查看

how can i put my PopupWindow to system desk or other app?


up vote1down votefavorite
1

how can i put my PopupWindow to system desk or other app? how can i use this permission:INTERNAL_SYSTEM_WINDOW
Any examples?Thanks!



android

link|edit|flag
asked Sep 17 '10 at 9:27



yuankai
417

0% accept rate
1
Weird Coincidence, Asked something similar hours ago...stackoverflow.com/questions/3732935/…st0leSep 17 '10 at 9:43
yes, i want to know how can it happens?i can't get any information about INTERNAL_SYSTEM_WINDOW,please help me if you know anything. – yuankai Sep 19 '10 at 1:12

3 Answers

activeoldestvotes

up vote0down vote
ok,the problem is resolved. i use WindowManager.addView in a service, and WindowManager.LayoutParams.type = TYPE_SYSTEM_ALERT, then it's ok! you can try it!

link|edit|flag
answered Sep 20 '10 at 15:35



yuankai
417

@yuankai, Could you please share the Source Code? I'd be very gratefull. :) – st0le Sep 21 '10 at 7:33
ok, how can i share my code here, can i put some files here? – yuankai Sep 21 '10 at 9:59
@yunkai, i didn't notice your comment till now...just edit your answer and put your code there. that'll do. Thanks a lot! :) – st0le Sep 27 '10 at 4:36
@yuankai, btw, FYI if you're addressing someone using comments use
@username
that'll notify that user of your comment. Cheers! :) – st0le Sep 27 '10 at 4:37
@st0le,thank you very much! – yuankai Oct 8 '10 at 1:14
up vote3down vote
public class PopupService extends Service implements IPopupTouchPosListener
{
public final static String FIELD_EVENT = "event";
/**
* 开启
*/
public final static int EVENT_SWITCH_ON = 1;

/**
* 关闭
*/
public final static int EVENT_SWITCH_OFF = 2;

private CustomPopupView mPopupView;
private int mCurrentY;

private RelativeLayout mLayout;

private WindowManager mWindowManager;
private WindowManager.LayoutParams mWmlp;

@Override
public void onCreate()
{
// TODO Auto-generated method stub
super.onCreate();

mWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);

// 获取屏幕宽度
DisplayMetrics outMetrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(outMetrics);
int width = outMetrics.widthPixels;

mWmlp = new WindowManager.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
mWmlp.alpha = 0.5f;
mWmlp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 不能抢占聚焦点
mWmlp.flags = mWmlp.flags | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
mWmlp.flags = mWmlp.flags | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; // 排版不受限制
mWmlp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;     // 系统提示类型
mWmlp.width = width;
mWmlp.height = 30;
mWmlp.gravity = 2;
mWmlp.format = -1;
mWmlp.token = null;
mWmlp.x = 0;
mWmlp.y = 200;

mCurrentY = mWmlp.y;

mLayout = new RelativeLayout(this);
mLayout.setBackgroundColor(0x00FFFFFF);
mLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));

mPopupView = new CustomPopupView(this);
mPopupView.setTouchPosListener(this);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, 30);

lp.bottomMargin = 0;
lp.leftMargin = 0;

mLayout.addView(mPopupView, lp);
}

@Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);

Log.i(Constants.LOG_TAG, "popup service onstart");

String action = intent.getAction();
if(action != null && action.equals(ActionDef.ACTION_POPUP_SERVICE))
{
Bundle bundle = intent.getExtras();
if(bundle != null)
{
int event = bundle.getInt(FIELD_EVENT);
if(event == EVENT_SWITCH_ON)
{
// 显示
mWindowManager.addView(mLayout, mWmlp);
}
else
{
mWindowManager.removeView(mLayout);
}
}
}
}

@Override
public IBinder onBind(Intent intent)
{
// TODO Auto-generated method stub
return null;
}

@Override
public void onMove(float x, float y)
{
if(mLayout != null)
{
Log.i(Constants.LOG_TAG, "y = " + y);
if(y > mLayout.getHeight())
{
mCurrentY = (int)y + mCurrentY - mLayout.getHeight();
}
else if(y < 0)
{
mCurrentY = (int)y + mCurrentY;
}

// 只更新位置
mWmlp.y = mCurrentY;
mWindowManager.updateViewLayout(mLayout, mWmlp);
}
}

}


link|edit|flag
answered Sep 28 '10 at 1:54



yuankai
417

there are some chinese words,you needn't care for it,just comment. – yuankai Sep 28 '10 at 2:16
@yuankai, thanks. – st0le Sep 28 '10 at 4:15
up vote0down vote
When I implement the code posted by @yuankai and add a Button view to the layout where he has a CustomPopupView, it appears as expected, over the top of all windows and responds to click events but won't change colour when pressed as Buttons normally do.
How can I update the button to change colour when depressed like its normal behaviour?

link|edit|flag
answered Dec 2 '10 at 10:50



deweylewie
133

you can get the click event when you setOnClickListener,and then change the color。 – yuankai Dec 9 '10 at 1:59
@yuankai Thanks, I worked it out by using setOnTouchListener and setting Button.setBackgroundDrawable manually. I now have a similar problem with a GestureOverlayView which isn't deleting gestures which have been performed. GestureOverlayView.clear(false) doesn't seem to be working. What's missing from this service-to-window procedure that an Activity normally has? – deweylewie Dec 9 '10 at 19:33
@deweylewie hi,i got nothing about GestureOverlayView,i think i cannot help you,sorry。 – yuankai Dec 15 '10 at 2:14
http://stackoverflow.com/questions/3734099/how-can-i-put-my-popupwindow-to-system-desk-or-other-app/3809160

creating a system overlay (always on top) button in android


up vote8down votefavorite
8

I'm trying to create an always-op-top button/clickable-image which stays on top of all the windows all the time. The proof of concept is here http://www.appbrain.com/app/smart-taskbar-%28sidebar%29/com.smart.taskbar and here http://forum.xda-developers.com/showthread.php?t=865525 I'm following this example code http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=services/java/com/android/server/LoadAverageService.java;h=0d86429aaa5ccf6ecf311dfb3af0f3ccbf5f8d29;hb=HEAD

I have been successful and have a running service now. The service displays some text on top left corner of screen all the time while user can freely interact with rest of apps in normal manner. What I'm doing is subclass ViewGroup and add it to root window manager with flag TYPE_SYSTEM_OVERLAY. Now I want to add a button/clickable-image in place of this text which can receive touch events on itself. I tried overriding "onTouchEvent" for the whole ViewGroup but it does not receive any event. How can I receive events only on certain parts of my always-on-top view group? Kindly suggest.
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AbsoluteLayout;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class HUD extends Service {
HUDView mView;

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

@Override
public void onCreate() {
super.onCreate();
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
mView = new HUDView(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
0,
//              WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
//                      | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.TOP;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);
}

@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getBaseContext(),"onDestroy", Toast.LENGTH_LONG).show();
if(mView != null)
{
((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(mView);
mView = null;
}
}
}

class HUDView extends ViewGroup {
private Paint mLoadPaint;

public HUDView(Context context) {
super(context);
Toast.makeText(getContext(),"HUDView", Toast.LENGTH_LONG).show();

mLoadPaint = new Paint();
mLoadPaint.setAntiAlias(true);
mLoadPaint.setTextSize(10);
mLoadPaint.setARGB(255, 255, 0, 0);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText("Hello World", 5, 15, mLoadPaint);
}

@Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
}

@Override
public boolean onTouchEvent(MotionEvent event) {
//return super.onTouchEvent(event);
Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
return true;
}
}




android

link|edit|flag
asked Dec 19 '10 at 1:57



coreSOLO
1207

100% accept rate
@coreSOLO, I hope you get you're answer, my oddly similar questions didnt get any response. :) +1 – st0leDec 19 '10 at 6:44
@st0le I promise I'll spend my night and day until I find the solution and share it with you :) – coreSOLO Dec 19 '10 at 8:02
@coreSOLO, hehe ;) – st0le Dec 19 '10 at 8:15
@st0le Ok maybe you and me can dig it out together, give me a link of your question and let me know how much progress you were able to make... – coreSOLO Dec 19 '10 at 9:01
its not much :-/ stackoverflow.com/questions/3732935/…st0le Dec 19 '10 at 9:40
show 1 more comment

3 Answers

activeoldestvotes

up vote5down voteaccepted
This might be a stupid solution. But it works. If you can improve it, please let me know.
OnCreate of your Service: I have usedWindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH flag. This is the only change in service.
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
mView = new HUDView(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.TOP;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);
}

Now, you will start getting each and every click event. So, you need to rectify in your event handler.
In your ViewGroup touch event
@Override public boolean onTouchEvent(MotionEvent event) {
// ATTENTION: GET THE X,Y OF EVENT FROM THE PARAMETER
// THEN CHECK IF THAT IS INSIDE YOUR DESIRED AREA

Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
return true;
}


link|edit|flag
answered Dec 19 '10 at 12:12



Sarwar Erfan
2,879114

AWESOME!!! Thanks a bunch. I'll try this out and let you know, but I know for sure that it works :) Yes I have a couple of possible improvements in mind for my original service which might optimize event handling. I'll let you know soon! Thanks again! – coreSOLO Dec 19 '10 at 14:02
can you give some more codes,when i run the code,but get more errors – pengwang Dec 27 '10 at 10:10
@pengwang: what errors are you getting? This code is not independent, you need to place them in your project with appropriate file names under appropriate project. – Sarwar Erfan Dec 28 '10 at 3:34
i am sorry,i only do it as a commom demo. can you give a easy demo in your blog or other link,so that i can study it.thank you – pengwang Dec 28 '10 at 3:45
1
@pengwang: Find simplest implementation here: docs.google.com/…Sarwar Erfan Dec 28 '10 at 12:07
show 4 more comments


up vote0down vote
It is not possible to get event in this fashion. You can only "display".
====== I have added a solution that worked for me. See my another reply.

link|edit|flag
edited Dec 19 '10 at 12:21

answered Dec 19 '10 at 5:55



Sarwar Erfan
2,879114

@Sarwar, i beg to differ, have you seen the
Smart Task Bar
app? It does handle click events... – st0le Dec 19 '10 at 6:45
Yes please, its already been done... – coreSOLO Dec 19 '10 at 8:01
depending how serious you are about this issue, how far you want to go, what is your ethical views, how much you understand assembly like code, how much you are interested in a particular app... there exists ways to partially discover what others are doing in their apps... But, lets see if anyone can provide a good answer in normal way. Voting up your question. – Sarwar Erfan Dec 19 '10 at 9:42
Thanks a lot. Ethically, its all about my ZTE Blade which has a shobby back button and I want to add an on screen back button, but in a much simpler way than the two implementations described above. I'm trying to contact original authors and just in case i'll get something i'll post it here too! – coreSOLO Dec 19 '10 at 9:53
I have got some success in testing... I will post after confirming. – Sarwar Erfan Dec 19 '10 at 11:39
show 1 more comment
up vote0down vote
Well try my code, atleast it gives you a string as overlay, you can very well replace it with a button or an image. You wont believe this is my first ever android app LOL. Anyways if you are more experienced with android apps than me, please try

changing parameters 2 and 3 in "new WindowManager.LayoutParams"

try some different event approach

link|edit|flag
answered Dec 19 '10 at 10:00



coreSOLO
1207

@coreSOLO, I've got over 8 months of Android behind me, but here's a thread that helped me earlier...stackoverflow.com/questions/3734099/…st0le Dec 19 '10 at 11:05
@coreSOLO, i eventually didnt find time to pursue this, hence i'm still scarce on its details... – st0le Dec 19 '10 at 11:06
http://stackoverflow.com/questions/4481226/creating-a-system-overlay-always-on-top-button-in-android
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐