Android layout 移动WindowManager中的ImageView不会';我不能正常工作
我正试图在屏幕上的所有东西(最上面)上画一个图标,类似于新的Facebook messenger的聊天头 我已经创建了一个在后台工作的服务,根据特定条件,我的图标应该出现在屏幕上(就像有人在facebook上向你发送消息时,messenger服务将挂起消息并在屏幕上显示聊天头,通知你新消息) 我所做的: 我已经创建了该服务,并授予它显示系统警报窗口的权限(因为头部实际上是一个系统警报窗口) 我从ImageView继承了一个类(StickyHeadView),并使用以下方式实现了OnTouchListener侦听器:Android layout 移动WindowManager中的ImageView不会';我不能正常工作,android-layout,xamarin.android,android-imageview,ontouchlistener,android-windowmanager,Android Layout,Xamarin.android,Android Imageview,Ontouchlistener,Android Windowmanager,我正试图在屏幕上的所有东西(最上面)上画一个图标,类似于新的Facebook messenger的聊天头 我已经创建了一个在后台工作的服务,根据特定条件,我的图标应该出现在屏幕上(就像有人在facebook上向你发送消息时,messenger服务将挂起消息并在屏幕上显示聊天头,通知你新消息) 我所做的: 我已经创建了该服务,并授予它显示系统警报窗口的权限(因为头部实际上是一个系统警报窗口) 我从ImageView继承了一个类(StickyHeadView),并使用以下方式实现了OnTouchLi
class StickyHeadView : ImageView, Android.Views.View.IOnTouchListener
{
private StickyHeadService OwnerService;
public StickyHeadView(StickyHeadService ContextService, Context context)
: base(context)
{
OwnerService = ContextService;
SetOnTouchListener(this);
}
float TouchMoveX;
float TouchMoveY;
public bool OnTouch(View v, MotionEvent e)
{
var windowService = OwnerService.GetSystemService(Android.Content.Context.WindowService);
var windowManager = windowService.JavaCast<Android.Views.IWindowManager>();
switch (e.Action & e.ActionMasked)
{
case MotionEventActions.Move:
TouchMoveX = (int)e.GetX();
TouchMoveY = (int)e.GetY();
OwnerService.LOParams.X = (int)(TouchMoveX);
OwnerService.LOParams.Y = (int)(TouchMoveY);
windowManager.UpdateViewLayout(this, OwnerService.LOParams);
Log.Debug("Point : ", "X: " + Convert.ToString(OwnerService.LOParams.X) + " Y: " + Convert.ToString(OwnerService.LOParams.Y));
return true;
case MotionEventActions.Down:
return true;
case MotionEventActions.Up:
return true;
}
return false;
}
}
class StickyHeadView:ImageView,Android.Views.View.IOnTouchListener
{
私人粘性服务所有者服务;
公共StickyHeadView(StickyHeadService上下文服务,上下文上下文)
:基本(上下文)
{
OwnerService=ContextService;
SetOnTouchListener(这个);
}
float-TouchMoveX;
浮动触摸移动;
公共bool OnTouch(视图v,运动事件e)
{
var windowService=OwnerService.GetSystemService(Android.Content.Context.windowService);
var windowManager=windowService.JavaCast();
开关(e.Action和e.ActionMasked)
{
case MotionEventActions。移动:
TouchMoveX=(int)e.GetX();
TouchMoveY=(int)e.GetY();
OwnerService.LOParams.X=(int)(TouchMoveX);
OwnerService.LOParams.Y=(int)(TouchMoveY);
windowManager.UpdateViewLayout(这是OwnerService.LOParams);
Log.Debug(“点:”,“X:“+Convert.ToString(OwnerService.LOParams.X)+“Y:+Convert.ToString(OwnerService.LOParams.Y));
返回true;
案例MotionEventActions.Down:
返回true;
case MotionEventActions.Up:
返回true;
}
返回false;
}
}
该服务具有wiindow manager以在其上显示图标…在服务“OnStart”事件中,我初始化头部:
private StickyHeadView MyHead;
public Android.Views.WindowManagerLayoutParams LOParams;
public override void OnStart(Android.Content.Intent intent, int startId)
{
base.OnStart(intent, startId);
var windowService = this.GetSystemService(Android.Content.Context.WindowService);
var windowManager = windowService.JavaCast<Android.Views.IWindowManager>();
MyHead = new StickyHeadView(this, this);
MyHead.SetImageResource(Resource.Drawable.Icon);
LOParams = new Android.Views.WindowManagerLayoutParams(Android.Views.WindowManagerLayoutParams.WrapContent,
Android.Views.WindowManagerLayoutParams.WrapContent,
Android.Views.WindowManagerTypes.Phone,
Android.Views.WindowManagerFlags.NotFocusable,
Android.Graphics.Format.Translucent);
LOParams.Gravity = GravityFlags.Top | GravityFlags.Left;
LOParams.X = 10;
LOParams.Y = 10;
windowManager.AddView(MyHead, LOParams);
}
private StickyHeadView MyHead;
public Android.Views.WindowManagerLayoutParams LOParams;
public override void OnStart(Android.Content.Intent Intent,int startId)
{
base.OnStart(intent,startId);
var windowService=this.GetSystemService(Android.Content.Context.windowService);
var windowManager=windowService.JavaCast();
MyHead=新的StickyHeadView(这个,这个);
SetImageResource(Resource.Drawable.Icon);
LOParams=新的Android.Views.WindowManagerLayoutParams(Android.Views.WindowManagerLayoutParams.WrapContent,
Android.Views.WindowManagerLayoutParams.WrapContent,
Android.Views.WindowManagerTypes.Phone,
Android.Views.WindowManagerFlags.NotFocusable,
Android.Graphics.Format.transparent);
LOParams.Gravity=GravityFlags.Top | GravityFlags.Left;
LOParams.X=10;
LOParams.Y=10;
windowManager.AddView(MyHead,LOParams);
}
如您所见,我声明了一个WindowManager,并使用特殊参数将视图(MyHead)添加到其中
我的问题:
当我试图移动视图(我的头)时,它不会以稳定的方式移动,并且会持续发生地震
我正在真正的HTC手机上使用安卓4.0.4进行测试
我用的是单机器人
请帮助…如果触摸的实现不正确,请建议更好的方法…谢谢。您使用的e.GetX()/eGetY()是相对于视图位置的,因此当您使用UpdateView布局移动视图时,下一个值将相对于移动。它使用GetRawX()/GetRawY()工作,但是您还必须跟踪初始的Down rawX和rawY
以下是我的JAVA代码:
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
layoutParams.x = Math.round(event.getRawX() - downX);
layoutParams.y = Math.round(event.getRawY() - downY);
windowManager.updateViewLayout(floatingView, layoutParams);
return true;
case MotionEvent.ACTION_DOWN:
downX = event.getRawX() - layoutParams.x;
downY = event.getRawY() - layoutParams.y;
return true;
case MotionEvent.ACTION_UP:
return true;
}
return false;
}
一句话,使用windowManager有一个很大的缺点。updateViewLayout(…)此方法每次移动都只会在浮动视图上调用Layout,这可能是一个性能问题,无论如何,到目前为止,我还没有找到另一种方法来移动浮动视图。试试这可能会有帮助 首先在活动中添加全局变量:
WindowManager wm;
LinearLayout lay;
float downX,downY;
在输入代码后,在活动中重新创建
Button btnstart=(Button)findViewById(R.id.button1);
Button btnstop=(Button)findViewById(R.id.button2);
btnstart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(lay==null)
{
wm = (WindowManager) getApplicationContext().getSystemService(
Context.WINDOW_SERVICE);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
| WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.x = (int) wm.getDefaultDisplay().getWidth();
params.y = 0;
// params.height = wm.getDefaultDisplay().getHeight()/2;
params.width = LayoutParams.WRAP_CONTENT;
params.format = PixelFormat.TRANSLUCENT;
params.gravity = Gravity.TOP | Gravity.LEFT;
params.setTitle("Info");
lay = null;
lay = new LinearLayout(getApplicationContext());
lay.setOrientation(LinearLayout.VERTICAL);
// lay.setAlpha(0.5f);
TextView txt_no = new TextView(getApplicationContext());
txt_no.setTextSize(10.0f);
txt_no.setText("Moving view by stack user!");
txt_no.setTextColor(Color.BLACK);
// txt_no.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
// LayoutParams.WRAP_CONTENT));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(0, 0, 0, 0); // margins as you wish
txt_no.setGravity(Gravity.RIGHT);
txt_no.setBackgroundColor(Color.WHITE);
txt_no.setLayoutParams(layoutParams);
txt_no.setPadding(10, 10, 10, 10);
lay.addView(txt_no);
AlphaAnimation alpha = new AlphaAnimation(0.5F, 0.5F);
alpha.setDuration(0); // Make animation instant
alpha.setFillAfter(true); // Tell it to persist after the animation ends
// And then on your layout
wm.addView(lay, params);
txt_no.startAnimation(alpha);
downX=params.x;
downY=params.y;
Log.v("MSES>", "x="+ downX +",y="+ downY);
lay.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
params.x = Math.round(event.getRawX() - downX);
params.y = Math.round(event.getRawY() - downY);
wm.updateViewLayout(lay, params);
Log.v("MSES EVENT>", "x="+ event.getRawX() +",y="+ event.getRawY());
Log.v("MSES MOVE>", "x="+ params.x +",y="+ params.y);
return true;
case MotionEvent.ACTION_DOWN:
downX = event.getRawX() - params.x;
downY = event.getRawY() - params.y;
Log.v("MSES DOWN>", "x="+ params.x +",y="+ params.y);
return true;
case MotionEvent.ACTION_UP:
//params.x = Math.round(event.getRawX() - downX);
//params.y = Math.round(event.getRawY() - downY);
//wm.updateViewLayout(lay, params);
return true;
}
return false;
}
});
}
}
});
btnstop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (lay != null) {
lay.removeAllViews();
wm.removeViewImmediate(lay);
lay = null;
}
}
});
在您的代码中只需使用
TYPE_SYSTEM_ALERT
或
而不是
TYPE_SYSTEM_OVERLAY
希望这对你有帮助
一个有效的例子:
@Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
chatHead = new ImageView(this);
chatHead.setImageResource(R.drawable.ic_launcher);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, //TYPE_PHONE
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 100;
windowManager.addView(chatHead, params);
chatHead.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
@Override public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(chatHead, params);
return true;
}
return false;
}
});
}
为什么没有人回答!我想这是一个提问的论坛!!!!那是java吗?你用什么编译器?
TYPE_SYSTEM_OVERLAY
@Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
chatHead = new ImageView(this);
chatHead.setImageResource(R.drawable.ic_launcher);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, //TYPE_PHONE
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 100;
windowManager.addView(chatHead, params);
chatHead.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
@Override public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(chatHead, params);
return true;
}
return false;
}
});
}