Android 데스크 톱 부상 창,몽 판 효과 인 스 턴 스 코드 구현
오늘 이 글 은 데스크 톱 부상 창 효 과 를 어떻게 실현 하 는 지 소개 하 는 것 이다.
우선 효과 도 를 보 세 요.
부유 창 은 모두 두 부분 으로 나 뉘 는데 하 나 는 보통 표시 되 는 작은 창 이 고 다른 하 나 는 작은 창 을 누 르 면 표시 되 는 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위 에서 말 한 것 은 안 드 로 이 드 가 데스크 톱 부상 창,몽 판 효과 인 스 턴 스 코드 를 실현 하 는 것 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.