发布于 2016-02-17 15:15:22 | 194 次阅读 | 评论: 0 | 来源: 网友投递

这里有新鲜出炉的精品教程,程序狗速度看过来!

Android移动端操作系统

Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安致”。


用到的就是WindowManager以及WindowManager.LayoutParams,对这个LayoutParams做文章,当设置为属性后,然后,创建一个View,将这个View添加到WindowManager中就行
一、前言:
我手机从来不装这些东西,不过,有次看到同事的android手机上,有个QQ管家在桌面上浮着,同事拖动管家时,管家就变成一只鸟,桌面下方还有个弹弓,桌面顶部有只乌鸦,把管家也就是鸟拖动到弹弓那,然后,松手,鸟就飞出去。这个过程是动画过程,做的事,实际上是清楚内存。

二:原理:
其实,没什么原理,用到的就是WindowManager以及WindowManager.LayoutParams,对这个LayoutParams做文章,当设置为属性后,然后,创建一个View,将这个View添加到WindowManager中就行。
 
package com.chris.floats.window; 
import android.os.Bundle; 
import android.util.DisplayMetrics; 
import android.view.Gravity; 
import android.view.WindowManager; 
import android.app.Activity; 
import android.content.Context; 
public class MainActivity extends Activity { 
private static WindowManager mWindowMgr = null; 
private WindowManager.LayoutParams mWindowMgrParams = null; 
private static FloatsWindowView mFloatsWindowView = null; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 
} 
/* 
* 显示应用主界面时,去除悬浮层 
*/ 
@Override 
public void onWindowFocusChanged(boolean hasFocus) { 
if(hasFocus){ 
if(mFloatsWindowView != null){ 
mWindowMgr.removeView(mFloatsWindowView); 
mFloatsWindowView = null; 
} 
}else{ 
getWindowLayout(); 
} 
} 
private void initParams(){ 
DisplayMetrics dm = getResources().getDisplayMetrics(); 
mWindowMgrParams.x = dm.widthPixels - 136; 
mWindowMgrParams.y = 300; 
mWindowMgrParams.width = 136; 
mWindowMgrParams.height = 136; 
} 
private void getWindowLayout(){ 
if(mFloatsWindowView == null){ 
mWindowMgr = (WindowManager)getBaseContext().getSystemService(Context.WINDOW_SERVICE); 
mWindowMgrParams = new WindowManager.LayoutParams(); 

/* 
* 2003 在指悬浮在所有界面之上 
* (4.0+系统中,在下拉菜单下面,而在2.3中,在上拉菜单之上) 
*/ 
mWindowMgrParams.type = 2003; 
mWindowMgrParams.format = 1; 

/* 
* 代码实际是wmParams.flags |= FLAG_NOT_FOCUSABLE; 
* 40的由来是wmParams的默认属性(32)+ FLAG_NOT_FOCUSABLE(8) 
*/ 
mWindowMgrParams.flags = 40; 
mWindowMgrParams.gravity = Gravity.LEFT | Gravity.TOP; 
initParams(); 

mFloatsWindowView = new FloatsWindowView(this); 
mWindowMgr.addView(mFloatsWindowView, mWindowMgrParams); 
} 
} 
} 

上面代码,主要在getWindowLayout函数中,最后两行就是创建一个View,并加入到WindowManager中。
继承View的悬浮View:
 
package com.chris.floats.window; 
import android.content.Context; 
import android.content.Intent; 
import android.graphics.drawable.AnimationDrawable; 
import android.util.AttributeSet; 
import android.util.DisplayMetrics; 
import android.view.Gravity; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.ViewTreeObserver.OnPreDrawListener; 
import android.view.WindowManager; 
public class FloatsWindowView extends View { 
private Context mContext = null; 
private WindowManager mWindowMgr = null; 
private WindowManager.LayoutParams mWindowMgrParams = null; 
private AnimationDrawable mAnimationDrawable = null; 

private int iPosX = 0; 
private int iPosY = 0; 
private int iLastPosX = 0; 
private int iLastPosY = 0; 
private boolean bMoved = false; 

public FloatsWindowView(Context context) { 
this(context, null, 0); 
} 
public FloatsWindowView(Context context, AttributeSet attrs) { 
this(context, attrs, 0); 
} 
public FloatsWindowView(Context context, AttributeSet attrs, int defStyle) { 
super(context, attrs, defStyle); 

mContext = context; 
mWindowMgr = (WindowManager)getContext().getApplicationContext().getSystemService("window"); 
mWindowMgrParams = new WindowManager.LayoutParams(); 
initParams(); 

mAnimationDrawable = new AnimationDrawable(); 
for(int i = 0; i < 4; i++){ 
int id = getResources().getIdentifier("a"+ i, "drawable", mContext.getPackageName()); 
mAnimationDrawable.addFrame(getResources().getDrawable(id), 100); 
} 
mAnimationDrawable.setOneShot(false); 
this.setBackgroundDrawable(mAnimationDrawable); 

OnPreDrawListener listener = new OnPreDrawListener(){ 
@Override 
public boolean onPreDraw() { 
mAnimationDrawable.start(); 
return true; 
} 
}; 
this.getViewTreeObserver().addOnPreDrawListener(listener); 
} 

private void initParams(){ 
DisplayMetrics dm = getResources().getDisplayMetrics(); 
mWindowMgrParams.x = dm.widthPixels - 136; 
mWindowMgrParams.y = 300; 
mWindowMgrParams.width = 136; 
mWindowMgrParams.height = 136; 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 

switch(event.getAction()){ 
case MotionEvent.ACTION_DOWN: 
iPosX = (int)event.getX(); 
iPosY = (int)event.getY(); 
bMoved = false; 
break; 

case MotionEvent.ACTION_MOVE: 
bMoved = true; 
iLastPosX = (int)event.getX(); 
iLastPosY = (int)event.getY(); 
updatePostion(iLastPosX - iPosX, iLastPosY - iPosY); 
break; 

case MotionEvent.ACTION_UP: 
if(!bMoved){ 
Intent it=new Intent(mContext, MainActivity.class); 
mContext.startActivity(it); 
} 
break; 

default: 
break; 
} 
return true; 
} 
private void updatePostion(int x, int y){ 
mWindowMgrParams.type = 2003; 
mWindowMgrParams.format = 1; 
mWindowMgrParams.flags = 40; 
mWindowMgrParams.gravity = Gravity.LEFT | Gravity.TOP; 
mWindowMgrParams.x += x; 
mWindowMgrParams.y += y; 
mWindowMgr.updateViewLayout(this, mWindowMgrParams); 
} 
} 

之所以将updatePosition中的参数与Activity中设置一样,是为了确保在MOVE时,造成相对位置的不一样,而导致闪砾,大家要是不理解,可以实验下。

三、小结:
这篇文章实现了简单的悬浮窗口动画效果,如果要想做成像360,QQ管家那样,还需要一些其它的操作:
1. 比如启动一个后台服务来监控系统信息;
2. ACTION_DOWN时,修改悬浮窗口上的图片;
3. ACTION_MOVE时窗口跟随;
4. ACTION_UP时,创建一个线程,来完成释放后,向上运动的动画过程等;

最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务