Android 데스크 톱 부상 창,몽 판 효과 인 스 턴 스 코드 구현

현재 많은 안전 소프트웨어,예 를 들 어 360 핸드폰 조수,바 이 두 핸드폰 조수 등 은 모두 부상 창 이 있어 데스크 톱 에 떠 서 사용자 가 자주 사용 하 는 조작 을 편리 하 게 할 수 있다.
오늘 이 글 은 데스크 톱 부상 창 효 과 를 어떻게 실현 하 는 지 소개 하 는 것 이다.
우선 효과 도 를 보 세 요.

부유 창 은 모두 두 부분 으로 나 뉘 는데 하 나 는 보통 표시 되 는 작은 창 이 고 다른 하 나 는 작은 창 을 누 르 면 표시 되 는 2 급 부유 창 이다.
우선 이 항목 의 디 렉 터 리 구 조 를 살 펴 보 세 요.

가장 중요 한 것 은 빨 간 테두리 안의 네 가지 유형 이다.
우선,Float Window Service 는 백 스테이지 서비스 클래스 로 백 스테이지 에서 데스크 톱 에 있 는 작은 부상 창 을 계속 새로 고침 하 는 것 을 책임 집 니 다.그렇지 않 으 면 인터페이스 가 바 뀌 면 부상 창 도 사라 지기 때문에 계속 새로 고침 해 야 합 니 다.다음은 구현 코드 입 니 다.

package com.qust.floatwindow; 
import java.util.Timer; 
import java.util.TimerTask; 
import android.app.Service; 
import android.content.Context; 
import android.content.Intent; 
import android.os.Handler; 
import android.os.IBinder; 
/** 
*         
* 
* @author zhaokaiqiang 
* 
*/ 
public class FloatWindowService extends Service { 
public static final String LAYOUT_RES_ID = "layoutResId"; 
public static final String ROOT_LAYOUT_ID = "rootLayoutId"; 
//         /  /      
private Handler handler = new Handler(); 
private Context context; 
private Timer timer; 
//        id 
private int layoutResId; 
//      id 
private int rootLayoutId; 
@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
context = this; 
layoutResId = intent.getIntExtra(LAYOUT_RES_ID, 0); 
rootLayoutId = intent.getIntExtra(ROOT_LAYOUT_ID, 0); 
if (layoutResId == 0 || rootLayoutId == 0) { 
throw new IllegalArgumentException( 
"layoutResId or rootLayoutId is illegal"); 
} 
if (timer == null) { 
timer = new Timer(); 
//  500            
timer.scheduleAtFixedRate(new RefreshTask(), 0, 500); 
} 
return super.onStartCommand(intent, flags, startId); 
} 
@Override 
public void onDestroy() { 
super.onDestroy(); 
// Service                 
timer.cancel(); 
timer = null; 
} 
private class RefreshTask extends TimerTask { 
@Override 
public void run() { 
//            ,      
if (!FloatWindowManager.getInstance(context).isWindowShowing()) { 
handler.post(new Runnable() { 
@Override 
public void run() { 
FloatWindowManager.getInstance(context) 
.createSmallWindow(context, layoutResId, 
rootLayoutId); 
} 
}); 
} 
} 
} 
@Override 
public IBinder onBind(Intent intent) { 
return null; 
} 
}
백 스테이지 서 비 스 를 제외 하고 저 희 는 두 개의 사용자 정의 레이아웃 이 필요 합 니 다.그것 이 바로 Float Window SmallView 와 Float Window BigView 입 니 다.이 두 개의 사용자 정의 레이아웃 은 주로 부상 창의 프론트 디 스 플레이 를 담당 합 니 다.저 희 는 각각 코드 실현 을 살 펴 보 겠 습 니 다.
우선 Float Window SmallView 류 의 실현 이다.

package com.qust.floatwindow; 
import java.lang.reflect.Field; 
import android.annotation.SuppressLint; 
import android.content.Context; 
import android.graphics.PixelFormat; 
import android.view.Gravity; 
import android.view.LayoutInflater; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.WindowManager; 
import android.widget.LinearLayout; 
import android.widget.TextView; 
import com.qust.demo.ScreenUtils; 
import com.qust.floatingwindow.R; 
/** 
*     ,       
* 
* @author zhaokaiqiang 
* 
*/ 
public class FloatWindowSmallView extends LinearLayout { 
//        
public int viewWidth; 
//        
public int viewHeight; 
//          
private static int statusBarHeight; 
//             
private WindowManager windowManager; 
//           
public WindowManager.LayoutParams smallWindowParams; 
//                  
private float xInScreen; 
//                  
private float yInScreen; 
//                ,         
private float xDownInScreen; 
//                ,         
private float yDownInScreen; 
//              View      
private float xInView; 
//              View      
private float yInView; 
//      
private OnClickListener listener; 
/** 
*      
* 
* @param context 
*       
* @param layoutResId 
*     id 
* @param rootLayoutId 
*    id 
*/ 
public FloatWindowSmallView(Context context, int layoutResId, 
int rootLayoutId) { 
super(context); 
windowManager = (WindowManager) context 
.getSystemService(Context.WINDOW_SERVICE); 
LayoutInflater.from(context).inflate(layoutResId, this); 
View view = findViewById(rootLayoutId); 
viewWidth = view.getLayoutParams().width; 
viewHeight = view.getLayoutParams().height; 
statusBarHeight = getStatusBarHeight(); 
TextView percentView = (TextView) findViewById(R.id.percent); 
percentView.setText("   "); 
smallWindowParams = new WindowManager.LayoutParams(); 
//        phone 
smallWindowParams.type = WindowManager.LayoutParams.TYPE_PHONE; 
//        
smallWindowParams.format = PixelFormat.RGBA_8888; 
//        
smallWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 
//           
smallWindowParams.gravity = Gravity.LEFT | Gravity.TOP; 
smallWindowParams.width = viewWidth; 
smallWindowParams.height = viewHeight; 
smallWindowParams.x = ScreenUtils.getScreenWidth(context); 
smallWindowParams.y = ScreenUtils.getScreenHeight(context) / 2; 
} 
@SuppressLint("ClickableViewAccessibility") 
@Override 
public boolean onTouchEvent(MotionEvent event) { 
switch (event.getAction()) { 
//             ,               
case MotionEvent.ACTION_DOWN: 
//              
xInView = event.getX(); 
yInView = event.getY(); 
//         ,      
xDownInScreen = event.getRawX(); 
yDownInScreen = event.getRawY() - statusBarHeight; 
break; 
case MotionEvent.ACTION_MOVE: 
//                  
xInScreen = event.getRawX(); 
yInScreen = event.getRawY() - statusBarHeight; 
//                  
updateViewPosition(); 
break; 
case MotionEvent.ACTION_UP: 
//          ,           ,           
if (xDownInScreen == event.getRawX() 
&& yDownInScreen == (event.getRawY() - getStatusBarHeight())) { 
if (listener != null) { 
listener.click(); 
} 
} 
break; 
} 
return true; 
} 
/** 
*             
*/ 
public void setOnClickListener(OnClickListener listener) { 
this.listener = listener; 
} 
/** 
*               
*/ 
private void updateViewPosition() { 
smallWindowParams.x = (int) (xInScreen - xInView); 
smallWindowParams.y = (int) (yInScreen - yInView); 
windowManager.updateViewLayout(this, smallWindowParams); 
} 
/** 
*          
* 
* @return 
*/ 
private int getStatusBarHeight() { 
try { 
Class<?> c = Class.forName("com.android.internal.R$dimen"); 
Object o = c.newInstance(); 
Field field = c.getField("status_bar_height"); 
int x = (Integer) field.get(o); 
return getResources().getDimensionPixelSize(x); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
return 0; 
} 
/** 
*      
* 
* @author zhaokaiqiang 
* 
*/ 
public interface OnClickListener { 
public void click(); 
} 
} 
이 클래스 에서 중요 한 작업 은 데스크 톱 전단 에 떠 있 는 창 을 실현 하 는 것 입 니 다.그리고 위치 이동 과 클릭 이벤트 의 판단 과 처리 입 니 다.여기 서 사용 하 는 것 은 주로 Window Manager 류 의 방법 과 속성 입 니 다.다음 편 은 상세 하 게 설명 할 것 입 니 다.이 편 은 실현 만 말 합 니 다.
작은 부상 창 을 제외 하고 클릭 한 후 나타 나 는 2 급 부상 창 도 데스크 톱 에 비슷 한 방식 으로 추 가 됩 니 다.다음은 2 급 부상 창의 코드 입 니 다.

package com.qust.floatwindow; 
import android.content.Context; 
import android.graphics.PixelFormat; 
import android.view.Gravity; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.WindowManager; 
import android.widget.LinearLayout; 
import android.widget.TextView; 
import com.qust.demo.ScreenUtils; 
import com.qust.floatingwindow.R; 
public class FloatWindowBigView extends LinearLayout { 
//          
public int viewWidth; 
//          
public int viewHeight; 
public WindowManager.LayoutParams bigWindowParams; 
private Context context; 
public FloatWindowBigView(Context context) { 
super(context); 
this.context = context; 
LayoutInflater.from(context).inflate(R.layout.float_window_big, this); 
View view = findViewById(R.id.big_window_layout); 
viewWidth = view.getLayoutParams().width; 
viewHeight = view.getLayoutParams().height; 
bigWindowParams = new WindowManager.LayoutParams(); 
//        ,         
bigWindowParams.x = ScreenUtils.getScreenWidth(context) / 2 - viewWidth 
/ 2; 
bigWindowParams.y = ScreenUtils.getScreenHeight(context) / 2 
- viewHeight / 2; 
bigWindowParams.type = WindowManager.LayoutParams.TYPE_PHONE; 
bigWindowParams.format = PixelFormat.RGBA_8888; 
//        
bigWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 
bigWindowParams.gravity = Gravity.LEFT | Gravity.TOP; 
bigWindowParams.width = viewWidth; 
bigWindowParams.height = viewHeight; 
initView(); 
} 
private void initView() { 
TextView tv_back = (TextView) findViewById(R.id.tv_back); 
tv_back.setOnClickListener(new OnClickListener() { 
@Override 
public void onClick(View v) { 
FloatWindowManager.getInstance(context).removeBigWindow(); 
} 
}); 
} 
} 
이러한 기본 적 인 클래스 가 만들어 진 후에 남 은 것 은 가장 중요 한 클래스 인 Float Window Manager 의 실현 이다.이런 종류의 실현 은 바로 부상 창 에 대한 조작 이다.

package com.qust.floatwindow; 
import android.content.Context; 
import android.content.Intent; 
import android.view.WindowManager; 
/** 
*        
* 
* @author zhaokaiqiang 
* 
*/ 
public class FloatWindowManager { 
//        
private FloatWindowSmallView smallWindow; 
//        
private FloatWindowBigView bigWindow; 
//                  
private WindowManager mWindowManager; 
// FloatWindowManager    
private static FloatWindowManager floatWindowManager; 
//       
private Context context; 
private FloatWindowManager(Context context) { 
this.context = context; 
} 
public static FloatWindowManager getInstance(Context context) { 
if (floatWindowManager == null) { 
floatWindowManager = new FloatWindowManager(context); 
} 
return floatWindowManager; 
} 
/** 
*        
* 
* @param context 
*         Context. 
*/ 
public void createSmallWindow(Context context, int layoutResId, 
int rootLayoutId) { 
WindowManager windowManager = getWindowManager(); 
if (smallWindow == null) { 
smallWindow = new FloatWindowSmallView(context, layoutResId, 
rootLayoutId); 
windowManager.addView(smallWindow, smallWindow.smallWindowParams); 
} 
} 
/** 
*             
* 
* @param context 
*/ 
public void removeSmallWindow() { 
if (smallWindow != null) { 
WindowManager windowManager = getWindowManager(); 
windowManager.removeView(smallWindow); 
smallWindow = null; 
} 
} 
public void setOnClickListener(FloatWindowSmallView.OnClickListener listener) { 
if (smallWindow != null) { 
smallWindow.setOnClickListener(listener); 
} 
} 
/** 
*        
* 
* @param context 
*         Context. 
*/ 
public void createBigWindow(Context context) { 
WindowManager windowManager = getWindowManager(); 
if (bigWindow == null) { 
bigWindow = new FloatWindowBigView(context); 
windowManager.addView(bigWindow, bigWindow.bigWindowParams); 
} 
} 
/** 
*             
* 
* @param context 
*/ 
public void removeBigWindow() { 
if (bigWindow != null) { 
WindowManager windowManager = getWindowManager(); 
windowManager.removeView(bigWindow); 
bigWindow = null; 
} 
} 
public void removeAll() { 
context.stopService(new Intent(context, FloatWindowService.class)); 
removeSmallWindow(); 
removeBigWindow(); 
} 
/** 
*         (          ) 
* 
* @return             true,      false 
*/ 
public boolean isWindowShowing() { 
return smallWindow != null || bigWindow != null; 
} 
/** 
*   WindowManager    ,     WindowManager  。          WindowManager 
* 
* @param context 
* @return 
*/ 
private WindowManager getWindowManager() { 
if (mWindowManager == null) { 
mWindowManager = (WindowManager) context 
.getSystemService(Context.WINDOW_SERVICE); 
} 
return mWindowManager; 
} 
} 
화면 너비 와 높이 를 가 져 오 는 도움말 클래스 도 있 습 니 다.

package com.qust.demo; 
import android.content.Context; 
import android.view.WindowManager; 
/** 
*       
* 
* @author zhaokaiqiang 
* 
*/ 
public class ScreenUtils { 
/** 
*        
* 
* @return 
*/ 
@SuppressWarnings("deprecation") 
public static int getScreenWidth(Context context) { 
return ((WindowManager) context 
.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay() 
.getWidth(); 
} 
/** 
*        
* 
* @return 
*/ 
@SuppressWarnings("deprecation") 
public static int getScreenHeight(Context context) { 
return ((WindowManager) context 
.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay() 
.getHeight(); 
} 
}
이것 을 완성 하면 우 리 는 직접 사용 할 수 있다.

package com.qust.demo; 
import android.app.Activity; 
import android.content.Context; 
import android.content.Intent; 
import android.os.Bundle; 
import android.view.KeyEvent; 
import android.view.View; 
import com.qust.floatingwindow.R; 
import com.qust.floatwindow.FloatWindowManager; 
import com.qust.floatwindow.FloatWindowService; 
import com.qust.floatwindow.FloatWindowSmallView.OnClickListener; 
/** 
*    
* 
* @ClassName: com.qust.demo.MainActivity 
* @Description: 
* @author zhaokaiqiang 
* @date 2014-10-23   11:30:13 
* 
*/ 
public class MainActivity extends Activity { 
private FloatWindowManager floatWindowManager; 
private Context context; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 
context = this; 
floatWindowManager = FloatWindowManager.getInstance(context); 
} 
/** 
*       
* 
* @param view 
*/ 
public void show(View view) { 
//           ,      id,       
Intent intent = new Intent(context, FloatWindowService.class); 
intent.putExtra(FloatWindowService.LAYOUT_RES_ID, 
R.layout.float_window_small); 
intent.putExtra(FloatWindowService.ROOT_LAYOUT_ID, 
R.id.small_window_layout); 
startService(intent); 
} 
/** 
*         
* 
* @param view 
*/ 
public void showBig(View view) { 
//             
floatWindowManager.setOnClickListener(new OnClickListener() { 
@Override 
public void click() { 
floatWindowManager.createBigWindow(context); 
} 
}); 
} 
/** 
*          
* 
* @param view 
*/ 
public void remove(View view) { 
floatWindowManager.removeAll(); 
} 
@Override 
public boolean onKeyDown(int keyCode, KeyEvent event) { 
//            
if (keyCode == KeyEvent.KEYCODE_BACK 
&& event.getAction() == KeyEvent.ACTION_DOWN) { 
floatWindowManager.removeBigWindow(); 
return true; 
} 
return super.onKeyDown(keyCode, event); 
} 
} 
프로젝트 다운로드 주소:https://github.com/ZhaoKaiQiang/FloatWindow
위의 글 에서 우 리 는 데스크 톱 부상 창 을 어떻게 실현 하 는 지 소개 했다.이 효 과 를 실현 하 는 과정 에서 가장 중요 한 유형 은 바로 Window Manager 이다.오늘 이 글 은 Window Manager 의 사용 에 대해 소개 하고 Window Manager 를 사용 하여 사용자 가 앱 을 열 어 처음으로 교육 몽 판 을 사용 하 는 효 과 를 나 타 낼 것 이다.
WindowManager 클래스 는 ViewManager 인 터 페 이 스 를 실현 합 니 다.ViewManager 인 터 페 이 스 는 Activity 에 view 를 추가 하거나 제거 할 수 있 습 니 다.따라서 WindowManager 는 Activity 에서 View 의 추가 와 제거 작업 을 할 수 있 습 니 다.
우 리 는 아래 의 방법 을 통 해 WindowManager 대상 을 얻 을 수 있다.

Context.getSystemService(Context.WINDOW_SERVICE)
Activity 에서 getWindowManager()를 통 해 WindowManager 대상 을 직접 얻 을 수 있 습 니 다.
모든 WindowManager 인 스 턴 스 는 하나의 디 스 플레이 대상 에 연결 되 어 있 습 니 다.서로 다른 디 스 플레이 의 WindowManager 대상 을 얻 으 려 면 createDisplayContext(Display)를 통 해 이 디 스 플레이 의 Context 대상 을 얻 은 다음 위의 방법 을 사용 하면 WindowManager 대상 을 얻 을 수 있 습 니 다.
우 리 는 Window Manager 클래스 를 사용 할 때 보통 다음 과 같은 몇 가지 방법 을 사용 합 니 다.

windowManager.addView(View,WindowManager.LayoutParam);
windowManager.removeView();
windowManager.getDefaultDisplay();
window Manager.addView()방법 은 현재 창 에 View 대상 을 추가 하 는 데 사 용 됩 니 다.두 개의 인 자 를 받 아들 여야 합 니 다.View 는 창 에 추가 할 View 대상 이 고 Window Manager.LayoutParam 은 추 가 된 창의 인자 입 니 다.이전 편 에 부상 창 을 추가 할 때 LayoutParam 에 많은 인 자 를 설정 해 야 합 니 다.다음은 자주 사용 하 는 설정 을 살 펴 보 겠 습 니 다.

//   LayoutParams   
LayoutParams params = new WindowManager.LayoutParams(); 
//       ,TYPE_PHONE             ,         ,     stateBar  ,            
params.type = WindowManager.LayoutParams.TYPE_PHONE; 
//       
params.format = PixelFormat.RGBA_8888; 
//       
params.gravity = Gravity.LEFT | Gravity.TOP; 
//     
params.width = ScreenUtils.getScreenWidth(this); 
params.height = ScreenUtils.getScreenHeight(this); 
//        
params.x; 
params.y; 
LayoutParam 을 설정 하면 window Manager.addView(View,Window Manager.LayoutParam)를 통 해 View 를 창 에 추가 할 수 있 습 니 다.단,권한 이 필요 합 니 다.

<uses-permissionAndroid:name="android.permission.SYSTEM_ALERT_WINDOW"/>
추가 가 완료 되면 창 에서 우리 가 추가 한 View 대상 을 볼 수 있 습 니 다.추가 한 View 를 제거 하려 면 window Manager.removeView()만 호출 하면 됩 니 다.매개 변 수 는 앞에서 사용 하 는 View 대상 입 니 다.사용 이 간단 합 니 다.이 방법 외 에 도 window Manager.removeView Immediate()도 있 습 니 다.View 를 제거 할 수 있 습 니 다.그러나 문서 에 서 는 이 방법 이 일반 프로그램 에 호출 되 는 것 이 아니 므 로 조심해 서 사용 해 야 합 니 다.우리 가 개발 한 것 은 모두 일반 프로그램 에 속 하 므 로 이 방법 을 사용 하지 않 는 것 을 권장 합 니 다.
이 두 가지 방법 을 제외 하고 우리 가 가장 자주 사용 하 는 또 다른 방법 은 window Manager.getDefault Display()입 니 다.이 방법 을 통 해 우 리 는 현재 인터페이스의 디 스 플레이 대상 을 얻 을 수 있 습 니 다.그리고 우 리 는 현재 화면의 일부 인 자 를 얻 을 수 있 습 니 다.예 를 들 어 너비 와 높이 등 입 니 다.
다음은 내 가 자주 사용 하 는 도구 류 이다.

package com.qust.teachmask; 
import android.content.Context; 
import android.view.WindowManager; 
/** 
*       
* 
* @author zhaokaiqiang 
* 
*/ 
public class ScreenUtils { 
/** 
*        
* 
* @return 
*/ 
@SuppressWarnings("deprecation") 
public static int getScreenWidth(Context context) { 
return ((WindowManager) context 
.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay() 
.getWidth(); 
} 
/** 
*        
* 
* @return 
*/ 
@SuppressWarnings("deprecation") 
public static int getScreenHeight(Context context) { 
return ((WindowManager) context 
.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay() 
.getHeight(); 
} 
} 

위의 이런 것들 을 알 게 된 후에 우 리 는 교육 모델 효 과 를 실현 할 수 있 고 먼저 효과 도 를 볼 수 있다.

다음은 코드 구현 입 니 다.

package com.qust.teachmask; 
import android.app.Activity; 
import android.graphics.PixelFormat; 
import android.os.Bundle; 
import android.view.Gravity; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.WindowManager; 
import android.view.WindowManager.LayoutParams; 
import android.widget.ImageView; 
import android.widget.ImageView.ScaleType; 
public class MainActivity extends Activity { 
private ImageView img; 
private WindowManager windowManager; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 
windowManager = getWindowManager(); 
//         
img = new ImageView(this); 
img.setLayoutParams(new LayoutParams( 
android.view.ViewGroup.LayoutParams.MATCH_PARENT, 
android.view.ViewGroup.LayoutParams.MATCH_PARENT)); 
img.setScaleType(ScaleType.FIT_XY); 
img.setImageResource(R.drawable.guide); 
//   LayoutParams   
LayoutParams params = new WindowManager.LayoutParams(); 
//        ,TYPE_PHONE             ,         ,     stateBar  ,            
params.type = WindowManager.LayoutParams.TYPE_PHONE; 
//        
params.format = PixelFormat.RGBA_8888; 
//        
params.gravity = Gravity.LEFT | Gravity.TOP; 
//      
params.width = ScreenUtils.getScreenWidth(this); 
params.height = ScreenUtils.getScreenHeight(this); 
//           
windowManager.addView(img, params); 
//       ,      
img.setOnClickListener(new OnClickListener() { 
@Override 
public void onClick(View arg0) { 
windowManager.removeView(img); 
} 
}); 
} 
} 
본 고 는 오리지널 이 아니 라 다음 과 같다.http://blog.csdn.net/zhaokaiqiang1992
위 에서 말 한 것 은 안 드 로 이 드 가 데스크 톱 부상 창,몽 판 효과 인 스 턴 스 코드 를 실현 하 는 것 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다!

좋은 웹페이지 즐겨찾기