Android中可自由移动悬浮窗口的实现
Android自定义悬浮按钮效果
Android⾃定义悬浮按钮效果本⽂实例为⼤家分享了Android⾃定义悬浮按钮效果的具体代码,供⼤家参考,具体内容如下以下:内容没有参考,写的也是⼀个⽐较简单的例⼦,主要就是应⽤切换前后台时会显⽰/隐藏悬浮窗。
内容仅⽤于⾃我记录学习使⽤。
项⽬的开发时应⽤在登陆后显⽰⼀个悬浮窗,同时显⽰在线⼈数等⼀些其他信息,点击悬浮按钮可以显⽰全局弹窗名单。
开发完成后,觉着需要记录⼀下这种实现⽅式。
所以写⼀个简单的Demo。
Demo思路是通过启动Service来添加/移除悬浮窗,因为是⼀个全局悬浮窗,所以选择依附于Service。
在MyAppliction中监听应⽤的前后台切换来添加或者隐藏悬浮窗。
其⾃定义的悬浮窗View在项⽬中是通过Canvas⼿动绘制的,这⾥图个省事直接加载⼀个布局⽂件。
主要是想理解这种添加全局悬浮窗的⽅式,所以Demo样式和功能能简则简。
MyApplictionpackage com.example.qxb_810.floatbuttondemo.application;import android.app.Activity;import android.app.ActivityManager;import android.app.Application;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.WindowManager;import com.example.qxb_810.floatbuttondemo.service.FloatingActionService;import java.util.List;import static android.content.ContentValues.TAG;/*** create 2018/12/1 13:31* desc ⾃定义Application*/public class MyApplication extends Application {private Intent mIntent;private youtParams mFloatingLayoutParams = new youtParams();public youtParams getmFloatingLayoutParams() {return mFloatingLayoutParams;}@Overridepublic void onCreate() {super.onCreate();this.monitorActivityLifecycle();}/*** 监听程序Activity声明周期*/private void monitorActivityLifecycle() {this.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {@Overridepublic void onActivityCreated(Activity activity, Bundle savedInstanceState) {}@Overridepublic void onActivityStarted(Activity activity) {if (isRunningForeground()){mIntent = new Intent(MyApplication.this, FloatingActionService.class);startService(mIntent);}}@Overridepublic void onActivityResumed(Activity activity) {}@Overridepublic void onActivityPaused(Activity activity) {}@Overridepublic void onActivityStopped(Activity activity) {if (!isRunningForeground()){stopService(mIntent);}}@Overridepublic void onActivitySaveInstanceState(Activity activity, Bundle outState) {}@Overridepublic void onActivityDestroyed(Activity activity) {}});}/*** 判断应⽤运⾏在前后台*/public boolean isRunningForeground() {ActivityManager activityManager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);List<ActivityManager.RunningAppProcessInfo> appProcessInfos = activityManager.getRunningAppProcesses(); // 枚举进程for (ActivityManager.RunningAppProcessInfo appProcessInfo : appProcessInfos) {if (appProcessInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {if (appProcessInfo.processName.equals(this.getApplicationInfo().processName)) {Log.d(TAG, "EntryActivity isRunningForeGround");return true;}}}Log.d(TAG, "EntryActivity isRunningBackGround");return false;}}FloatingActionService.java ---- 悬浮窗所依附的Servicepackage com.example.qxb_810.floatbuttondemo.service;import android.app.Service;import android.content.Intent;import android.graphics.PixelFormat;import android.os.IBinder;import android.support.annotation.Nullable;import android.util.DisplayMetrics;import android.view.Display;import android.view.Gravity;import android.view.WindowManager;import android.widget.LinearLayout;import android.widget.Toast;import com.example.qxb_810.floatbuttondemo.application.MyApplication;import com.example.qxb_810.floatbuttondemo.button.FloatingActionButton;/*** create 2018/12/1 13:34* desc 悬浮按钮Service*/public class FloatingActionService extends Service {private WindowManager mWindowManager;private FloatingActionButton mButton;private int mScreenWidth;private int mScreenHeight;@Overridepublic void onCreate() {super.onCreate();this.initView();this.initEvent();}@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {super.onDestroy();this.mWindowManager.removeViewImmediate(this.mButton);}/*** 添加按钮*/private void initView() {// 通过WindowManager来添加悬浮窗this.mWindowManager = (WindowManager) this.getApplicationContext().getSystemService(WINDOW_SERVICE);Display display = this.mWindowManager.getDefaultDisplay();DisplayMetrics metrics = new DisplayMetrics();display.getMetrics(metrics);this.mScreenWidth = metrics.widthPixels;this.mScreenHeight = metrics.heightPixels;youtParams params = ((MyApplication) this.getApplication()).getmFloatingLayoutParams();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {mFloatingLayoutParams.type = youtParams.TYPE_APPLICATION_OVERLAY;} else {mFloatingLayoutParams.type = youtParams.TYPE_TOAST;}params.format = PixelFormat.RGBA_8888;params.flags = youtParams.FLAG_NOT_TOUCH_MODAL | youtParams.FLAG_NOT_FOCUSABLE; params.gravity = Gravity.LEFT | Gravity.TOP; // 左上为坐标点// 设置View⼤⼩params.height = 50;params.width = 50;// 设置View坐标位置params.x = 0;params.y = mScreenHeight / 2;this.mButton = FloatingActionButton.getInstance(this);this.mWindowManager.addView(mButton, params);}/*** 初始化事件*/private void initEvent() {this.mButton.setOnClickListener(v -> {// 项⽬中是在这⾥进⾏添加名单弹窗和移除名单弹窗的操作,但名单弹窗的初始化不在这⾥Toast.makeText(this, "点击了Button", Toast.LENGTH_SHORT).show();});}}FloatingActionButton – 弹窗按钮package com.example.qxb_810.floatbuttondemo.button;import android.content.Context;import android.graphics.Canvas;import android.support.annotation.Nullable;import android.util.AttributeSet;import youtInflater;import android.view.MotionEvent;import android.view.View;import android.view.WindowManager;import android.widget.FrameLayout;import android.widget.LinearLayout;import com.example.qxb_810.floatbuttondemo.R;import com.example.qxb_810.floatbuttondemo.application.MyApplication;import static android.content.Context.WINDOW_SERVICE;/*** create 2018/12/1 13:35* desc ⾃定义悬浮按钮 -- 这⾥随便写的⼀个布局⽂件*/public class FloatingActionButton extends FrameLayout {private Context mContext;private float mStartPointX;private float mStartPointY;private WindowManager mWindowManager;private youtParams mFloatingLayoutParams;private boolean isIntercept = false;private int mStatusHeight;public static FloatingActionButton getInstance(Context context) {FloatingActionButton button = new FloatingActionButton(context);return button;}public FloatingActionButton(Context context) {this(context, null);}public FloatingActionButton(Context context, @Nullable AttributeSet attrs) {this(context, attrs, -1);}public FloatingActionButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mContext = context;initView();}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);}/*** 初始化View*/private void initView(){// 随便添加⼀个简单的View布局作为悬浮窗View view = LayoutInflater.from(mContext).inflate(yout_floating_button, null, false);youtParams params = new youtParams(youtParams.WRAP_CONTENT,youtParams.WRAP_CONTENT); this.addView(view, params);this.mWindowManager = (WindowManager) getContext().getApplicationContext().getSystemService(WINDOW_SERVICE);this.mFloatingLayoutParams = ((MyApplication) getContext().getApplicationContext()).getmFloatingLayoutParams();this.mStatusHeight = getStatusHeight(mContext);}@Overridepublic boolean onTouchEvent(MotionEvent event) {//获取相对屏幕的坐标,即以屏幕左上⾓为原点float rawX = event.getRawX();float rawY = event.getRawY() - mStatusHeight; //statusHeight是系统状态栏的⾼度switch (event.getAction()){case MotionEvent.ACTION_DOWN:this.mStartPointX = event.getX();this.mStartPointY = event.getY();isIntercept = false;break;case MotionEvent.ACTION_MOVE:mFloatingLayoutParams.x = (int)(rawX - mStartPointX);mFloatingLayoutParams.y = (int)(rawY - mStartPointY);this.mWindowManager.updateViewLayout(this, mFloatingLayoutParams);isIntercept = true;break;case MotionEvent.ACTION_UP:mFloatingLayoutParams.x = 0; // 这⾥的策略是默认松⼿吸附到左侧如果需要吸附到右侧则改为mFloatingLayoutParams.x = mScreenWidth; mScreenWidth 是屏幕宽度,不想吸附则注释这⼀句即可 this.mWindowManager.updateViewLayout(this, mFloatingLayoutParams);break;}return isIntercept ? isIntercept : super.onTouchEvent(event);}/*** 状态栏的⾼度*/public static int getStatusHeight(Context context) {int statusHeight = -1;try {Class clazz = Class.forName("com.android.internal.R$dimen"); //使⽤反射获取实例Object object = clazz.newInstance();int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());statusHeight = context.getResources().getDimensionPixelSize(height);} catch (Exception e) {e.printStackTrace();}return statusHeight;}}布局⽂件<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:background="@color/colorPrimary"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="12312313131313"android:textSize="20sp" /></LinearLayout>以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
android 小米 自由窗口 实现原理
android 小米自由窗口实现原理一、引言Android系统中的小米自由窗口技术,是一种新型的显示和计算技术,具有高效率、低功耗等优点。
本篇文章将详细介绍自由窗口的实现原理,从硬件支持到软件设计,深入探讨自由窗口的技术特点和应用场景。
二、硬件支持小米自由窗口技术的实现,离不开其内置的显示芯片。
通过硬件级支持,显示芯片能够实现高效的多窗口处理,从而为自由窗口的实现提供了基础。
在硬件层面,显示芯片能够将多个窗口无缝拼接,实现高效的多任务处理。
三、软件设计自由窗口的实现主要依赖于Android系统中的WindowManager和SurfaceFlinger等API。
通过这些API,开发者可以创建和管理多个窗口,并在不同窗口之间进行切换。
自由窗口的核心思想是将应用程序的界面拆分成多个小窗口,这些窗口可以在屏幕上同时显示,从而实现高效的多任务处理。
每个窗口可以独立绘制,互不干扰,大大提高了显示效率。
四、技术特点1.高效率:自由窗口技术通过并行处理多个窗口,实现了高效的显示和计算。
多个窗口可以同时绘制,大大提高了显示效率。
2.低功耗:由于自由窗口技术可以独立绘制窗口,互不干扰,因此可以减少不必要的画面刷新,降低功耗。
3.可定制性强:开发者可以根据自己的需求,定制窗口的大小、位置、透明度等属性,以满足不同的应用场景。
五、应用场景1.多任务处理:自由窗口技术适用于需要同时处理多个任务的应用场景,如多任务办公、游戏等。
2.多媒体播放:自由窗口技术可以同时播放多个音视频文件,实现高效的多媒体播放。
3.视频会议:自由窗口技术适用于需要同时展示会议资料和视频会议界面的场景,提高会议效率。
六、总结小米自由窗口技术的实现原理主要依赖于硬件的支持和软件的优化设计。
通过将应用程序的界面拆分成多个小窗口,并在屏幕上同时显示,实现了高效的多任务处理。
自由窗口技术具有高效率、低功耗、可定制性强等优点,适用于多任务处理、多媒体播放和视频会议等多种应用场景。
Android利用WindowManager生成悬浮按钮及悬浮菜单
Android利⽤WindowManager⽣成悬浮按钮及悬浮菜单简介本⽂模仿实现的是360⼿机卫⼠基础效果,同时后续会补充⼀些WindowManager的原理知识。
整体思路360⼿机卫⼠的内存球其实就是⼀个没有画⾯的应⽤程序,整个应⽤程序的主体是⼀个Service。
我们的程序开始以后,启动⼀个service,同时关闭activity即可:public class MainActivity extends Activity {private static final String TAG = MainActivity.class.getSimpleName();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);startService(new Intent(this, FloatWindowService.class));finish();}}import android.os.IBinder;import android.util.Log;import java.util.Timer;import java.util.TimerTask;public class FloatWindowService extends Service {private static final String TAG = FloatWindowService.class.getSimpleName();public FloatWindowService() {}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.d(TAG, "on start command");FloatWindowManager.instance(getApplicationContext()).createFloatWindow();return super.onStartCommand(intent, flags, startId);}@Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.throw new UnsupportedOperationException("Not yet implemented");}}我们要注意的是,传统的Service默认是运⾏在UI线程中的,这点与封装了⼀个Thread和Handler的intentService不同,所以我们可以直接在Service中更改UI相关的内容。
android Activity实现从底部弹出或滑出选择菜单或窗口
博客分类:
•android Activity
android Activity实现从底部弹出菜单或窗口android Activity滑出选择菜单或窗口androidActivity
本例使用activity实现弹出滑动窗口或菜单,主要是使用了一些设置activity的样式来实现弹出窗口和滑动效果,实现如下:
第一步:设计要弹出窗口的xml布局:
Xml代码
第二步:创建SelectPicPopupWindow类继承Activity类并实现OnClickListener接口(可以不用在这里实现这个借口,根据自己需要和方便实现),其他代码实现跟编写常规Activity 一样就OK,如下:
Java代码
第三步:编写MainActivity类,这里很简单就是点击启动刚才要实现窗口的MainActivity 即可:
Java代码
第四步:这里要注意下AndroidManifest.xml对SelectPicPopupWindow的配置跟常规的不一样为该activity改添加android:theme属性,如下:
Xml代码
第五步:这一步是实现本实例最重要的一部就是设置android:theme属性样式以实现本例所需要的效果,如下:
Xml代码
第六步:在贴出弹出和销毁时的动画效果代码:
push_bottom_in.xml
Xml代码
push_buttom_out.xml
Xml代码
注意:这两个xml需要放在res/anim的anim文件夹下第七步;运行效果如图:。
Android悬浮窗的简单实现
Android悬浮窗的简单实现⽬录概述原理Android的界⾯绘制,都是通过 WindowManager 的服务来实现的。
WindowManager 实现了 ViewManager 接⼝,可以通过获取 WINDOW_SERVICE 系统服务得到。
⽽ViewManager 接⼝有 addView ⽅法,我们就是通过这个⽅法将悬浮窗控件加⼊到屏幕中去。
为了让悬浮窗与Activity脱离,使其在应⽤处于后台时悬浮窗仍然可以正常运⾏,使⽤Service来启动悬浮窗并做为其背后逻辑⽀撑。
权限在 API Level >= 23 的时候,需要在AndroidManefest.xml⽂件中声明权限 SYSTEM_ALERT_WINDOW 才能在其他应⽤上绘制控件。
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />除了这个权限外,我们还需要在系统设置⾥⾯对本应⽤进⾏设置悬浮窗权限。
该权限在应⽤中需要启动 Settings.ACTION_MANAGE_OVERLAY_PERMISSION 来让⽤户⼿动设置权限。
if (!Settings.canDrawOverlays(this)) {showError("当前⽆权限,请授权");startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 0);} else {startService(new Intent(MainActivity.this, FloatingService.class));}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == 0) {if (!Settings.canDrawOverlays(this)) {showError("授权失败");} else {showMsg("授权成功");startService(new Intent(MainActivity.this, FloatingService.class));}}}LayoutParamWindowManager 的 addView ⽅法有两个参数,⼀个是需要加⼊的控件对象,另⼀个参数是 youtParam 对象。
Android中可自由移动悬浮窗口的实现xsmilesBlog
Android中可自由移动悬浮窗口的实现xsmilesBlog Android中可自由移动悬浮窗口的实现2011年7月27日android, 技术相关7 评论第二届 Google 暑期大学生博客分享大赛 – 2011 Android 成长篇本文为参加Google暑期大学生博客分享大赛特别撰写。
—————————————————————-大家对悬浮窗概念不会陌生,相信每台电脑桌面的右上角都会有这么一个东西,它总是出现在所有页面的顶端(Top Show)。
但在Android平台中如何实现这样的效果呢?先来看一看效果图。
看见在Google搜索框上面的那个Icon图片了嘛。
下面我就来详细介绍一下在Android平台下悬浮窗口的实现,并让它能够随手指的触摸而移动。
一、实现原理及移动思路调用WindowManager,并设置youtParams的相关属性,通过WindowManager的addView方法创建View,这样产生出来的View根据youtParams属性不同,效果也就不同了。
比如创建系统顶级窗口,实现悬浮窗口效果!然后通过覆写悬浮View中onTouchEvent方法来改变youtParams中x和y的值来实现自由移动悬浮窗口。
二、示例代码先来看一看悬浮View的代码,这里用一个ImageView作为演示01public class MyFloatView extends ImageView {02 private float mTouchStartX;03 private float mTouchStartY;04 private float x;05 private float y;0607 private WindowManager wm=(WindowManager)getContext().getApplicationContext().getSystemService("window");08 //此wmParams变量为获取的全局变量,用以保存悬浮窗口的属性09 private youtParams wmParams =((MyApplication)getContext().getApplicationContext()).getMywmParams();1011 public MyFloatView(Context context) {12 super(context);13 // TODO Auto-generated constructor stub14 }1516 @Override17 public boolean onTouchEvent(MotionEvent event) {18 //获取相对屏幕的坐标,即以屏幕左上角为原点19 x = event.getRawX();20 y = event.getRawY()-25; //25是系统状态栏的高度21 Log.i("currP", "currX"+x+"====currY"+y);22 switch(event.getAction()) {23 case MotionEvent.ACTION_DOWN: //捕获手指触摸按下动作24 //获取相对View的坐标,即以此View左上角为原点25 mTouchStartX = event.getX();26 mTouchStartY = event.getY();27 Log.i("startP","startX"+mTouchStartX+"====startY"+mTouchStartY);28 break;2930 case MotionEvent.ACTION_MOVE: //捕获手指触摸移动动作31 updateViewPosition();32 break;3334 case MotionEvent.ACTION_UP: //捕获手指触摸离开动作35 updateViewPosition();36 mTouchStartX=mTouchStartY=0;37 break;38 }39 return true;40 }4142 private void updateViewPosition(){43 //更新浮动窗口位置参数44 wmParams.x=(int)( x-mTouchStartX);45 wmParams.y=(int) (y-mTouchStartY);46 wm.updateViewLayout(this, wmParams); //刷新显示47 }4849}上面的wmParams变量(即youtParams)的存储采用了extends Application的方式来创建全局变量,示例代码如下:01public class MyApplication extends Application {0203 /**04 * 创建全局变量05 * 全局变量一般都比较倾向于创建一个单独的数据类文件,并使用static静态变量06 *07 * 这里使用了在Application中添加数据的方法实现全局变量08 * 注意在AndroidManifest.xml中的Application节点添加android:name=".MyApplication"属性09 *10 */11 private youtParams wmParams=new youtParams(); 1213 public youtParams getMywmParams(){14 return wmParams;15 }16}再来看一看Activity中的代码:01public class MyFloatViewActivity extends Activity {02 /** Called when the activity is first created. */0304 private WindowManager wm=null;05 private youtParams wmParams=null;0607 private MyFloatView myFV=null;080910 @Override11 public void onCreate(Bundle savedInstanceState) {12 super.onCreate(savedInstanceState);13 setContentView(yout.main);14 //创建悬浮窗口15 createView();1617 }18192021 private void createView(){22 myFV=new MyFloatView(getApplicationContext());23 myFV.setImageResource(R.drawable.icon); //这里简单的用自带的Icom来做演示24 //获取WindowManager25 wm=(WindowManager)getApplicationContext().getSystemService("window");26 //设置LayoutParams(全局变量)相关参数27 wmParams = ((MyApplication)getApplication()).getMywmParams();2829 /**30 *以下都是youtParams的相关属性31 * 具体用途可参考SDK文档32 */33 wmParams.type=LayoutParams.TYPE_PHONE; //设置window type34 wmParams.format=PixelFormat.RGBA_8888; //设置图片格式,效果为背景透明3536 //设置Window flag37 wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL38 | LayoutParams.FLAG_NOT_FOCUSABLE;39 /*40 * 下面的flags属性的效果形同“锁定”。
Android实现控件悬浮效果实例代码
Android实现控件悬浮效果实例代码随着移动互联⽹的快速发展,它已经和我们的⽣活息息相关了,在公交地铁⾥⾯都能看到很多⼈的⼈低头看着⾃⼰的⼿机屏幕,从此“低头族”⼀词就产⽣了,作为⼀名移动⾏业的开发⼈员,我⾃⼰也是⼀名“低头族”,上下班时间在公交地铁上看看新闻来打发下时间,有时候也会看看那些受欢迎的App的⼀些界⾯效果,为什么⼈家的app那么受欢迎?跟⽤户体验跟UI设计也有直接的关系,最近在美团和⼤众点评的App看到如下效果,我感觉⽤户好,很⼈性化,所以⾃⼰也尝试着实现了下,接下来就讲解下实现思路!如上图(2)我们看到了,当⽴即抢购布局向上滑动到导航栏布局的时候,⽴即抢购布局就贴在导航栏布局下⾯,下⾯的其他的布局还是可以滑动,当我们向下滑动的时候,⽴即抢购的布局⼜随着往下滑动了,看似有点复杂,但是⼀说思路可能你就顿时恍然⼤悟了。
当我们向上滑动过程中,我们判断⽴即抢购的布局是否滑到导航栏布局下⾯,如果⽴即抢购的上⾯顶到了导航栏,我们新建⼀个⽴即抢购的悬浮框来显⽰在导航栏下⾯,这样⼦就实现了⽴即抢购贴在导航栏下⾯的效果啦,⽽当我们向下滑动的时候,当⽴即抢购布局的下⾯刚好到了刚刚新建的⽴即抢购悬浮框的下⾯的时候,我们就移除⽴即抢购悬浮框,可能说的有点拗⼝,既然知道了思路,接下来我们就来实现效果。
新建⼀个Android项⽬,取名MeiTuanDemo,先看⽴即抢购(buy_layout.xml)的布局,这⾥为了⽅便我直接从美团上⾯截去了图⽚<?xml version="1.0" encoding="UTF-8"?><LinearLayout xmlns:android="/apk/res/android"android:orientation="horizontal"android:layout_width="fill_parent"android:layout_height="wrap_content" ><ImageViewandroid:id="@+id/buy_layout"android:layout_width="fill_parent"android:layout_height="wrap_content"android:background="@drawable/buy" /></LinearLayout>⽴即抢购的布局实现了,接下来实现主界⾯的布局,上⾯是导航栏布局,为了⽅便还是直接从美团截取的图⽚,然后下⾯的ViewPager布局,⽴即抢购布局,其他布局放在ScrollView⾥⾯,界⾯还是很简单的<LinearLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/imageView1"android:scaleType="centerCrop"android:layout_width="match_parent"android:layout_height="45dip"android:src="@drawable/navigation_bar" /><com.example.meituandemo.MyScrollViewandroid:id="@+id/scrollView"android:layout_width="fill_parent"android:layout_height="fill_parent" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" ><ImageViewandroid:id="@+id/iamge"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/pic"android:scaleType="centerCrop" /><includeandroid:id="@+id/buy"layout="@layout/buy_layout" /><ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/one"android:scaleType="centerCrop" /><ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/one"android:scaleType="centerCrop" /><ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/one"android:scaleType="centerCrop" /></LinearLayout></com.example.meituandemo.MyScrollView></LinearLayout>你会发现上⾯的主界⾯布局中并不是ScrollView,⽽是⾃定义的⼀个MyScrollView,接下来就看看MyScrollView类中的代码package com.example.meituandemo;import android.content.Context;import android.os.Handler;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.ScrollView;/*** 博客地址:/xiaanming** @author xiaanming**/public class MyScrollView extends ScrollView {private OnScrollListener onScrollListener;/*** 主要是⽤在⽤户⼿指离开MyScrollView,MyScrollView还在继续滑动,我们⽤来保存Y的距离,然后做⽐较*/private int lastScrollY;public MyScrollView(Context context) {this(context, null);public MyScrollView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyScrollView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}/*** 设置滚动接⼝* @param onScrollListener*/public void setOnScrollListener(OnScrollListener onScrollListener) {this.onScrollListener = onScrollListener;}/*** ⽤于⽤户⼿指离开MyScrollView的时候获取MyScrollView滚动的Y距离,然后回调给onScroll⽅法中 */private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {int scrollY = MyScrollView.this.getScrollY();//此时的距离和记录下的距离不相等,在隔5毫秒给handler发送消息if(lastScrollY != scrollY){lastScrollY = scrollY;handler.sendMessageDelayed(handler.obtainMessage(), 5);}if(onScrollListener != null){onScrollListener.onScroll(scrollY);}};};/*** 重写onTouchEvent,当⽤户的⼿在MyScrollView上⾯的时候,* 直接将MyScrollView滑动的Y⽅向距离回调给onScroll⽅法中,当⽤户抬起⼿的时候,* MyScrollView可能还在滑动,所以当⽤户抬起⼿我们隔5毫秒给handler发送消息,在handler处理 * MyScrollView滑动的距离*/@Overridepublic boolean onTouchEvent(MotionEvent ev) {if(onScrollListener != null){onScrollListener.onScroll(lastScrollY = this.getScrollY());}switch(ev.getAction()){case MotionEvent.ACTION_UP:handler.sendMessageDelayed(handler.obtainMessage(), 5);break;}return super.onTouchEvent(ev);}/**** 滚动的回调接⼝** @author xiaanming**/public interface OnScrollListener{/*** 回调⽅法,返回MyScrollView滑动的Y⽅向距离* @param scrollY* 、*/public void onScroll(int scrollY);}}⼀看代码你也许明⽩了,就是对ScrollView的滚动Y值进⾏监听,我们知道ScrollView并没有实现滚动监听,所以我们必须⾃⾏实现对ScrollView的监听,我们很⾃然的想到在onTouchEvent()⽅法中实现对滚动Y轴进⾏监听,可是你会发现,我们在滑动ScrollView的时候,当我们⼿指离开ScrollView。
Android创建悬浮窗的完整步骤
Android创建悬浮窗的完整步骤在Android中想要创建悬浮窗分为三步1.申请权限2.使⽤服务启动悬浮窗3.设置悬浮窗参数并添加进WindowManager下⾯话不多说了,来⼀起看看详细的实现过程申请权限⾸先需要申请悬浮窗权限,在清单⽂件中 manifest 下添加<!-- 低版本悬浮窗所需权限 --><uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>在Activity中动态申请权限public class MainActivity extends Activity {/** 悬浮窗权限标识码 */public static final int CODE_WINDOW = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 申请悬浮窗权限if (Build.VERSION.SDK_INT >= 23) {if (!Settings.canDrawOverlays(this)) {Toast.makeText(this, "请打开此应⽤悬浮窗权限-Shendi", Toast.LENGTH_SHORT).show();startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), CODE_WINDOW); }}// 关闭当前activity,这样只显⽰悬浮窗finish();}// 权限申请成功后的回调@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {switch (requestCode) {// 不给权限就退出case Permission.CODE_WINDOW:if (resultCode != Activity.RESULT_OK) System.exit(0);break;default:Toast.makeText(this, "未知权限回调: " + requestCode, Toast.LENGTH_SHORT).show();}}}使⽤服务启动悬浮窗对于悬浮窗的操作主要使⽤ WindowManager创建⼀个服务,并在清单⽂件中注册public class TestService extends Service {@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return super.onStartCommand(intent, flags, startId);}@Overridepublic IBinder onBind(Intent intent) {return null;}}在清单⽂件的Application中注册服务<service android:name=".TestService" />在Activity中启动服务Intent intent = new Intent(this, TestService.class);startService(intent);接下来需要创建悬浮窗的界⾯,这⾥⽅便演⽰直接使⽤代码创建也可以使⽤inflate函数将xml⽂件变view对象View.inflate(context, yout.main_activity, null);在服务的onStartCommand函数中内容如下@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Button btn = new Button(this);btn.setText("hello,world");return super.onStartCommand(intent, flags, startId);}设置悬浮窗参数并添加进WindowManager这⾥直接上代码,看注释@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Button btn = new Button(this);btn.setText("hello,world");// 获取WindowManagerWindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); // 创建布局参数youtParams params = new youtParams(); /** 设置参数 */params.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?youtParams.TYPE_APPLICATION_OVERLAY :youtParams.TYPE_PHONE;params.format = PixelFormat.RGBA_8888;// 设置窗⼝的⾏为准则params.flags = youtParams.FLAG_NOT_FOCUSABLE;//设置透明度params.alpha = 1.0f;//设置内部视图对齐⽅式,这边位置为左边靠上params.gravity = Gravity.LEFT | Gravity.TOP;//窗⼝的左上⾓坐标params.x = 0;params.y = 0;//设置窗⼝的宽⾼,这⾥为⾃动params.width = youtParams.WRAP_CONTENT;params.height = youtParams.WRAP_CONTENT;// 添加进WindowManagerwm.addView(btn, params);return super.onStartCommand(intent, flags, startId);}完整代码如下TestActivitypackage shendi.app.game.robot;import android.app.Activity;import android.content.Intent;import .Uri;import android.os.Build;import android.os.Bundle;import android.provider.Settings;import android.widget.Toast;public class TestActivity extends Activity {/** 悬浮窗权限标识码 */public static final int CODE_WINDOW = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 申请悬浮窗权限if (Build.VERSION.SDK_INT >= 23) {if (!Settings.canDrawOverlays(this)) {Toast.makeText(this, "请打开此应⽤悬浮窗权限-Shendi", Toast.LENGTH_SHORT).show();startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), CODE_WINDOW); }}Intent intent = new Intent(this, TestService.class);startService(intent);// 关闭当前activity,这样只显⽰悬浮窗finish();}// 权限申请成功后的回调@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {switch (requestCode) {// 不给权限就退出case Permission.CODE_WINDOW:if (resultCode != Activity.RESULT_OK) System.exit(0);break;default:Toast.makeText(this, "未知权限回调: " + requestCode, Toast.LENGTH_SHORT).show();}}}TestServicepackage shendi.app.game.robot;import android.app.Service;import android.content.Intent;import android.graphics.PixelFormat;import android.os.Build;import android.os.IBinder;import android.view.Gravity;import android.view.WindowManager;import android.widget.Button;public class TestService extends Service {@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Button btn = new Button(this);btn.setText("hello,world");// 获取WindowManagerWindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);// 创建布局参数youtParams params = new youtParams();/** 设置参数 */params.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?youtParams.TYPE_APPLICATION_OVERLAY :youtParams.TYPE_PHONE;params.format = PixelFormat.RGBA_8888;// 设置窗⼝的⾏为准则params.flags = youtParams.FLAG_NOT_FOCUSABLE;//设置透明度params.alpha = 1.0f;//设置内部视图对齐⽅式,这边位置为左边靠上params.gravity = Gravity.LEFT | Gravity.TOP;//窗⼝的左上⾓坐标params.x = 0;params.y = 0;//设置窗⼝的宽⾼,这⾥为⾃动params.width = youtParams.WRAP_CONTENT;params.height = youtParams.WRAP_CONTENT;// 添加进WindowManagerwm.addView(btn, params);return super.onStartCommand(intent, flags, startId);}@Overridepublic IBinder onBind(Intent intent) {return null;}}运⾏ app,可以在屏幕左上⾓看到 hello,world的按钮悬浮拖动效果给悬浮组件添加触碰事件可以实现拖动效果,按钮组件不适⽤这⾥给出简单的实现代码⽚段private int upX, upY;// 视图移动处理view.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getActionMasked()) {case MotionEvent.ACTION_DOWN:upX = (int) event.getRawX();upY = (int) event.getRawY();break;case MotionEvent.ACTION_MOVE:// 与上⼀次位置相差不到5则不移动if (event.getRawX() - upX > 5 || event.getRawY() - upY > 5) {params.x = (int) event.getRawX();params.y = (int) event.getRawY();wm.updateViewLayout(view, params);}break;case MotionEvent.ACTION_UP:// 相差不到5则代表点击if (event.getRawX() - upX < 5 && event.getRawY() - upY < 5) {// TODO}break;}return false;}});移除悬浮窗可以在 onDestry 函数中进⾏移除@Overridepublic void onDestroy() {wm.removeView(view);super.onDestroy();}总结到此这篇关于Android创建悬浮窗的⽂章就介绍到这了,更多相关Android悬浮窗内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。
Android中的悬浮对话框和即点即关对话框
Android中的悬浮对话框和即点即关对话框Activity是Ophone系统的4个应用程序组件之一。
通过传统方法显示的Activity都是充满整个屏幕,也就是全屏的Activity。
事实上,Activity不仅可以全屏显示,还可以象对话框一样直接显示在屏幕上。
而且可以通过单击屏幕的任何位置(包括Activity内部和Activity 外部)来关闭Activity。
Activity的传统风格Activity是学习Ophone的入门技术。
几乎所有的初学者都会从Activity学起。
因此,Activity这个组件对于Ophone的开发人员是再熟悉不过了。
下面来看一下Activity的基本配置。
<activity android:name=".Main" android:label="@string/app_name"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="UNCHER"/></intent-filter></activity>上面的配置代码是一个典型的Activity配置。
在这个配置中主要指定了action和category。
按着这个配置显示的Activity会充满整个屏幕。
在Ophone中也内置了很多程序,大多数都会包含Activity,例如,图1是一个时钟程序,也是一个典型的Activity。
悬浮Activity所谓悬浮Activity,就是悬浮在桌面上,看起来象一个对话框。
如图2所示。
事实上,实现上面的效果并不复杂,只需要在AndroidManifest.xml文件中定义Activity 的<activity>标签中添加一个android:theme属性,并指定对话框主题即可,代码如下:<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schem /apk/res/android" package="net.blogjava.mobile"android:versionCode="1"android:versionName="1.0"><application android:icon="@drawable/date"android:label="@string/app_name"><activity android:name=".Main" android:label="@string/app_name"android:them e="@android:style/Them e.Dialog"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="UNCHER"/></intent-filter></activity></application><uses-sdk android:minSdkVersion="3"/></manifest>当使用上面的配置代码时,显示的Activity就会如图2所示。
Android实现系统级悬浮按钮
Android实现系统级悬浮按钮本⽂实例为⼤家分享了Android系统级悬浮按钮的具体代码,供⼤家参考,具体内容如下具体的需求1、就是做⼀个系统级的悬浮按钮,就像iPhone 桌⾯的那个悬浮按钮效果⼀样,能随意拖动,并且⼿⼀放开,悬浮按钮就⾃动靠边。
2、可以点击并且可以随意拖动。
3、悬浮按钮⾃动靠边的时候,或者移动到边上的时候,⾃动隐藏半边。
4、横竖屏切换都兼容1、就在WindowManager ⾥⾯添加View,这个View通过⾃定义控件来实现。
2、在onTouch⾥的MotionEvent.ACTION_MOVE事件⾥头,通过控制悬浮按钮的具体坐标来实现随意移动。
3、在onTouch⾥的MotionEvent.ACTION_UP事件⾥头,来控制悬浮按钮⾃动靠边,并且⾃动隐藏半边,不过在这⾥onTouch和onClick这两个事件是⼀起触发的,不过这也有解决办法,你可以在⼿放开的瞬间,通过移动的距离,来决定是否触发点击事件,,如果返回false,就会触发点击事件,如果返回true就会触发点击事件4、通过⾃定义控件onLayout⽅法,来捕获横竖屏切换事件,5、还有⼀个靠哪边停靠的问题,通过坐标来判读更靠近哪⼀边。
就靠哪边停靠。
![以中间这个中⼼点为准,以更短的X轴画⼀个正⽅形]下⾯是具体实现代码:import android.content.Context;import android.graphics.Canvas;import android.graphics.Point;import android.graphics.Rect;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.WindowManager;import android.widget.ImageView;import com.iapppay.openid.channel.LoginResultCallback;import com.iapppay.openid.channel.OpenIDApplication;import com.iapppay.openid.channel.util.DisplayUtil;import com.iapppay.openid.channel.util.LogUtil;import com.iapppay.openid.channel.util.Res;/*** Created by HuangTiebing 2017/2/14.*/public class DragFloatActionButton extends ImageView implements View.OnTouchListener, View.OnClickListener {public static String TAG = "DragFloatActionButton";private Context context;float lastX, lastY;float originX, originY;int screenWidth;int screenHeight;private int originWidth;private WindowManager windowManager;// // 此windowManagerParams变量为获取的全局变量,⽤以保存悬浮窗⼝的属性private youtParams windowManagerParams;private LoginResultCallback resultCallback; //悬浮按钮点击回调public DragFloatActionButton(Context context, boolean isForceLogin, LoginResultCallback resultCallback) {this(context, null);OpenIDApplication.getInstance().setForceLogin(isForceLogin);this.resultCallback = resultCallback;}public DragFloatActionButton(Context context, AttributeSet attrs) {this(context, attrs, 0);}public DragFloatActionButton(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);this.context = context;Point screenSize = DisplayUtil.getScreenSize(context);screenWidth = screenSize.x;screenHeight = screenSize.y;setImageResource(Res.drawable(context, "ipay_float_btn_bg"));setOnTouchListener(this);setOnClickListener(this);windowManager = (WindowManager) getContext().getApplicationContext().getSystemService(Context.WINDOW_SERVICE); }public int getOriginWidth() {return originWidth;}public void setOriginWidth(int originWidth) {this.originWidth = originWidth;}@Overridepublic boolean onTouch(View v, MotionEvent event) {windowManagerParams = (youtParams) this.getLayoutParams();//获取到状态栏的⾼度Rect frame = new Rect();getWindowVisibleDisplayFrame(frame);int ea = event.getAction();switch (ea) {case MotionEvent.ACTION_DOWN:lastX = event.getRawX();// 获取触摸事件触摸位置的原始X坐标lastY = event.getRawY();originX = lastX;originY = lastY;break;case MotionEvent.ACTION_MOVE:float dx = event.getRawX() - lastX;float dy = event.getRawY() - lastY;windowManagerParams.x += dx;windowManagerParams.y += dy;LogUtil.d(TAG, "移动距离:dx=" + dx + ",dy=" + dy);showAllBtn();lastX = (int) event.getRawX();lastY = (int) event.getRawY();break;case MotionEvent.ACTION_UP:float lastMoveDx = Math.abs(event.getRawX() - originX);float lastMoveDy = Math.abs(event.getRawY() - originY);LogUtil.d(TAG, "松开时,移动距离:lastMoveDx=" + lastMoveDx + ", lastMoveDy=" + lastMoveDy);if (lastMoveDx < 10 && lastMoveDy < 10) { //移动距离太⼩,视为点击,return false;} else {updateViewLayout(event);isFirstClick = true;return true;}}return false;}/*** 显⽰整个图标*/public void showAllBtn() {windowManagerParams.width = originWidth;windowManagerParams.height = originWidth;setImageResource(Res.drawable(context, "ipay_float_btn_bg"));windowManager.updateViewLayout(this, windowManagerParams); // 刷新显⽰}/*** 悬浮按钮显⽰在左边*/private void showInLeft() {windowManagerParams.x = 0;windowManagerParams.width = originWidth / 2;windowManagerParams.height = originWidth;setImageResource(Res.drawable(context, "ipay_float_btn_left_hidden"));windowManager.updateViewLayout(this, windowManagerParams); // 刷新显⽰ }/*** 悬浮按钮显⽰在右边*/private void showInRight() {windowManagerParams.width = originWidth / 2;windowManagerParams.height = originWidth;windowManagerParams.x = screenWidth - windowManagerParams.width;setImageResource(Res.drawable(context, "ipay_float_btn_right_hidden"));windowManager.updateViewLayout(this, windowManagerParams); // 刷新显⽰ }/*** 悬浮按钮显⽰在上⾯*/private void showInTop() {windowManagerParams.y = 0;windowManagerParams.width = originWidth;windowManagerParams.height = originWidth / 2;setImageResource(Res.drawable(context, "ipay_float_btn_top_hidden"));windowManager.updateViewLayout(this, windowManagerParams); // 刷新显⽰ }/*** 悬浮按钮显⽰在下⾯*/private void showInBottom() {windowManagerParams.width = originWidth;windowManagerParams.height = originWidth / 2;windowManagerParams.y = screenHeight - windowManagerParams.width;setImageResource(Res.drawable(context, "ipay_float_btn_bottom_hidden")); windowManager.updateViewLayout(this, windowManagerParams); // 刷新显⽰ }/*** 更新悬浮图标** @param event ⼿动移动事件*/public void updateViewLayout(MotionEvent event) {Point center = new Point(screenWidth / 2, screenHeight / 2); //屏幕中⼼点float xOffset, yOffset;//以屏幕中⼼点为原点,X轴和Y轴上的偏移量if (event != null) {//⼿动移动的xOffset = event.getRawX() - center.x;yOffset = event.getRawY() - center.y;} else {//⾃动隐藏xOffset = lastX - center.x;yOffset = lastY - center.y;}if (Math.abs(xOffset) >= Math.abs(yOffset)) {//向左或向右缩进隐藏if (xOffset <= 0) { //向左缩进showInLeft();} else {showInRight();}} else {//向上或向下缩进隐藏if (yOffset <= 0) {//向上缩进showInTop();} else {showInBottom();}}}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);Point screenSize = DisplayUtil.getScreenSize(context);if (screenWidth != screenSize.x) {//屏幕旋转切换screenWidth = screenSize.x;screenHeight = screenSize.y;lastY = windowManagerParams.x;lastX = windowManagerParams.y;windowManagerParams.x = (int) lastX;windowManagerParams.y = (int) lastY;updateViewLayout(null);}}private boolean isFirstClick = true;@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);}@Overridepublic void onClick(View v) {LogUtil.d(TAG, "执⾏点击事件");if (!isFirstClick) {OpenIDApplication.getInstance().floatBtnClick(context, OpenIDApplication.getInstance().isForceLogin(), resultCallback);} else {//半隐藏状态,点击显⽰全部isFirstClick = false;showAllBtn();}}}调⽤实现代码,这⾥注意有个问题,弹出系统级的悬浮窗,需要配置权限:并且Android 6.0以上的⼿机,还要弹出对话框问⽤户是否运⾏,如果这个⽤户拒绝了,就不能弹出系统级的悬浮窗了,还有个别⼿机⼚商修改了android源码,还需要进系统设置⾥去允许这个应⽤弹出悬浮窗。
Android悬浮Activity并可拖动(仿悬浮歌词)
Android悬浮Activity并可拖动(仿悬浮歌词)Android⼿机上的⾳乐播放器,相信不少朋友都曾⽤过。
不知⼤家是否注意到,有⼀个迷你歌词的特效。
什么效果呢?就是不管你切到什么画⾯,歌词永远显⽰,并且可以拖动。
在电脑上播放时显⽰的歌词效果。
这个歌词是在所有界⾯之上的。
下⾯我们将这个效果解剖⼀下,我认为主要有三个难点:1. 歌词悬浮在所有页⾯之上2. 歌词可以拖动位置对于第⼀点,⾸先想到的就是 WindowManager ,这个类可能不少⼈都⽤过,⼀般⽤于获取屏幕宽度、⾼度,那么这次就要利⽤这个类来让我们的歌词永远置顶。
通过查看API,我们看到,在youtParams类中,有好⼏个属性可以设置View置顶。
下⾯我们来测试⼀下, 通过下⾯⼏句代码,就可以让⼀个View凌驾在所有View之上。
WindowManager wm = (WindowManager)getApplicationContext().getSystemService(WINDOW_SERVICE);youtParams params = new youtParams();params.type = youtParams.TYPE_SYSTEM_OVERLAY;params.width = youtParams.WRAP_CONTENT;params.height = youtParams.WRAP_CONTENT;TextView tv = new TextView(this);wm.addView(tv, params);这边需要注意的是, WindowManager也是通过 getSystemService 来获取,但必须getApplicationContext,否则就⽆效了。
直接WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE); 这样是⽆效的!!还有⼀点就是,别忘了在Manifest.xml中添加权限:<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> 现在我们这样做,我们已经可以让歌词永远置顶了。
android中实现悬浮窗口并滚动
android中实现悬浮窗口并滚动(2012-08-27 11:36:55)转载▼标签:it因为项目需要最近研究了android中实现悬浮并滚动的效果,笔记如下。
首先要实现一个自己画的滚动View.import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.view.Display;import android.view.View;import android.view.WindowManager;import android.view.View.OnClickListener;import android.widget.TextView;public class AutoScroll extends TextView {private float textLength = 0f;//文本长度private float viewWidth = 0f;private float step = 0f;//文字的横坐标private float y = 0f;//文字的纵坐标private float temp_view_plus_text_length = 0.0f;//用于计算的临时变量private float temp_view_plus_two_text_length = 0.0f;//用于计算的临时变量 public boolean isStarting = false;//是否开始滚动private Paint paint = null;//绘图样式private String text = "";//文本内容Canvas acanvas;private Handler handler = new Handler(){@Overridepublic void handleMessage(Message msg){onDraw(acanvas);}};public AutoScroll(Context context){super(context);// initView();}public AutoScroll(Context context, AttributeSet attrs){super(context, attrs);// initView();}public AutoScroll(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);// initView();}// public void onClick(View v) {// if(isStarting)// stopScroll();// else// startScroll();// }// private void initView()// {// setOnClickListener(this);// }public void init(WindowManager windowManager){paint = getPaint();text = getText().toString();textLength = paint.measureText(text);//textview中字数的长度viewWidth = getWidth();if(viewWidth == 0){if(windowManager != null){Display display = windowManager.getDefaultDisplay();viewWidth = display.getWidth();}}step = textLength;temp_view_plus_text_length = viewWidth + textLength;temp_view_plus_two_text_length = viewWidth + textLength * 2;y = getTextSize() + getPaddingTop();}public void startScroll(){isStarting = true;invalidate();}public void stopScroll(){isStarting = false;invalidate();}public void onDraw(Canvas canvas) {acanvas = canvas;canvas.drawText(text, temp_view_plus_text_length - step, y, paint); if(!isStarting){return;}step += 2;//0.5为文字滚动速度。
Android中悬浮窗口的实现原理和示例代码
WindowManager的方法很简单,基本用到的就三个addView,removeView,updateViewLayout。
而youtParams的属性就多了,非常丰富,具体请查看SDK文档。这里给出Android中的WindowManager.java源码,可以具体看一下。
下面是简单示例代码:
public class myFloatView extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
* These windows are normally placed above all applications, but behind
* the status bar.
*/
public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;
用了我一个周末的时间,个中愤懑就不说了,就这个问题,我翻遍全球网络没有一篇像样的资料,现在将实现原理简单叙述如下:
调用WindowManager,并设置youtParams的相关属性,通过WindowManager的addView方法创建View,这样产生出来的View根据youtParams属性不同,效果也就不同了。比如创建系统顶级窗口,实现悬浮窗口效果!
wm.addView(bb, wmParams); //创建View
}
}
别忘了在AndroidManifest.xml中添加权限:
Android桌面悬浮窗效果实现
49. // 当前界⾯不是桌⾯,且有悬浮窗显⽰,则移除悬浮窗。
50. else if (!isHome() && MyWindowManager.isWindowShowing()) {51. handler.post(new Runnable() {52. @Override53. public void run() {54. MyWindowManager.removeSmallWindow(getApplicationContext());55. MyWindowManager.removeBigWindow(getApplicationContext());56. }57. });58. }59. // 当前界⾯是桌⾯,且有悬浮窗显⽰,则更新内存数据。
60. else if (isHome() && MyWindowManager.isWindowShowing()) {61. handler.post(new Runnable() {62. @Override63. public void run() {64. MyWindowManager.updateUsedPercent(getApplicationContext());65. }66. });67. }68. }69.70. }71.72. /**73. * 判断当前界⾯是否是桌⾯74. */75. private boolean isHome() {76. ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);77. List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);78. return getHomes().contains(rti.get(0).topActivity.getPackageName());79. }80.81. /**82. * 获得属于桌⾯的应⽤的应⽤包名称83. *84. * @return 返回包含所有包名的字符串列表85. */86. private List<String> getHomes() {87. List<String> names = new ArrayList<String>();88. PackageManager packageManager = this.getPackageManager();89. Intent intent = new Intent(Intent.ACTION_MAIN);90. intent.addCategory(Intent.CATEGORY_HOME);91. List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,92. PackageManager.MATCH_DEFAULT_ONLY);93. for (ResolveInfo ri : resolveInfo) {94. names.add(ri.activityInfo.packageName);95. }96. return names;97. }98. }FloatWindowService的onStartCommand⽅法中开启了⼀个定时器,每隔500毫秒就会执⾏RefreshTask。
Android实现全局悬浮框
Android实现全局悬浮框本⽂实例为⼤家分享了Android实现全局悬浮框的具体代码,供⼤家参考,具体内容如下效果图:代码实现:Androidmanifest.xml添加弹框权限<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />⾃定义悬浮窗类FloatWindow.javapublic class FloatWindow implements View.OnTouchListener {private Context mContext;private youtParams mWindowParams;private WindowManager mWindowManager;private View mFloatLayout;private float mInViewX;private float mInViewY;private float mDownInScreenX;private float mDownInScreenY;private float mInScreenX;private float mInScreenY;private TextView infoText;public FloatWindow(Context context) {this.mContext = context;initFloatWindow();}private void initFloatWindow() {LayoutInflater inflater = LayoutInflater.from(mContext);if(inflater == null)return;mFloatLayout = (View) inflater.inflate(yout_float, null);infoText = mFloatLayout.findViewById(R.id.textView);mFloatLayout.setOnTouchListener(this);mWindowParams = new youtParams();mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);if (Build.VERSION.SDK_INT >= 26) {//8.0新特性mWindowParams.type = youtParams.TYPE_APPLICATION_OVERLAY;}else{mWindowParams.type = youtParams.TYPE_SYSTEM_ALERT;}mWindowParams.format = PixelFormat.RGBA_8888;mWindowParams.flags = youtParams.FLAG_NOT_FOCUSABLE;mWindowParams.gravity = Gravity.START | Gravity.TOP;mWindowParams.width = youtParams.WRAP_CONTENT;mWindowParams.height = youtParams.WRAP_CONTENT;}@Overridepublic boolean onTouch(View view, MotionEvent motionEvent) {return floatLayoutTouch(motionEvent);}private boolean floatLayoutTouch(MotionEvent motionEvent) {switch (motionEvent.getAction()) {case MotionEvent.ACTION_DOWN:// 获取相对View的坐标,即以此View左上⾓为原点mInViewX = motionEvent.getX();mInViewY = motionEvent.getY();// 获取相对屏幕的坐标,即以屏幕左上⾓为原点mDownInScreenX = motionEvent.getRawX();mDownInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext);mInScreenX = motionEvent.getRawX();mInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext);break;case MotionEvent.ACTION_MOVE:// 更新浮动窗⼝位置参数mInScreenX = motionEvent.getRawX();mInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext);mWindowParams.x = (int) (mInScreenX- mInViewX);mWindowParams.y = (int) (mInScreenY - mInViewY);// ⼿指移动的时候更新⼩悬浮窗的位置mWindowManager.updateViewLayout(mFloatLayout, mWindowParams);break;case MotionEvent.ACTION_UP:// 如果⼿指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。
Android实现悬浮窗的简单方法实例
Android实现悬浮窗的简单⽅法实例⽬录1. 前⾔2.原理3.具体实现3.1浮窗布局3.2 悬浮窗的实现1. 使⽤服务Service2. 获取WindowManager并设置LayoutParams3. 创建View并添加到WindowManager4. 实现悬浮窗的拖拽和关闭功能5. 利⽤⼴播进⾏通信6. 设置权限3.3 完整代码4. 总结1. 前⾔现在很多应⽤都有⼩悬浮窗的功能,⽐如看直播的时候,通过Home键返回桌⾯,直播的⼩窗⼝仍可以在屏幕上显⽰。
下⾯将介绍下悬浮窗的的⼀种简单实现⽅式。
2.原理Window我们应该很熟悉,它是⼀个接⼝类,具体的实现类为PhoneWindow,它可以对View进⾏管理。
WindowManager是⼀个接⼝类,继承⾃ViewManager,从名称就知道它是⽤来管理Window的,它的实现类是WindowManagerImpl。
如果我们想要对Window(View)进⾏添加、更新和删除操作就可以使⽤WindowManager,WindowManager会将具体的⼯作交由WindowManagerService处理。
这⾥我们只需要知道WindowManager能⽤来管理Window就好。
WindowManager是⼀个接⼝类,继承⾃ViewManager,ViewManager中定义了3个⽅法,分布⽤来添加、更新和删除View,如下所⽰:public interface ViewManager {public void addView(View view, youtParams params);public void updateViewLayout(View view, youtParams params);public void removeView(View view);}WindowManager也继承了这些⽅法,⽽这些⽅法传⼊的参数都是View类型,说明了Window是以View的形式存在的。
android floatwindow使用方法
android floatwindow使用方法如何使用Android FloatWindow在Android 开发中,FloatWindow 是一个非常有用的功能,它可以在应用程序的顶部显示一个浮动窗口,在用户的视图之上。
这使得我们可以轻松地实现一些悬浮按钮、通知、广告、提示等功能。
在本文中,我们将介绍如何使用FloatWindow,并提供一步一步的指导。
步骤一:添加依赖库首先,我们需要在项目的build.gradle 文件中添加FloatWindow 的依赖库。
在dependencies 部分,添加以下行:dependencies {implementation 'com.yhao.floatwindow:floatwindow:1.0.1'}然后点击Sync Now,Gradle 将自动下载并导入所需的库文件。
步骤二:在AndroidManifest.xml 文件中添加权限FloatWindow 功能需要一些系统级权限才能正常工作,因此我们需要在AndroidManifest.xml 文件中添加以下权限:xml<uses-permissionandroid:name="android.permission.SYSTEM_ALERT_WINDOW" />步骤三:创建一个FloatWindow 的布局文件在res/layout 目录下,创建一个名为float_window_layout.xml 的布局文件。
在该文件中,我们可以定义要在浮动窗口中显示的视图内容。
以下是一个简单的示例:xml<LinearLayout xmlns:android="android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#FFFFFF"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="Hello FloatWindow!" /><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="Close" /></LinearLayout>步骤四:实现FloatWindow 功能在我们的代码中,我们将使用一个名为FloatWindow 的类来实现FloatWindow 的基本功能。
Android利用WindowManager实现悬浮窗
Android利⽤WindowManager实现悬浮窗前⾔你会发现QQ视频的时候,就算⼿机回到主页,视频⼩模块依旧能悬浮在桌⾯上。
还有当年很⽕的各种⼿机杀毒软件的桌⾯⼩助⼿,总能在呆在桌⾯。
这种悬浮窗的操作就需要⽤到Window。
效果gif图看着有点⼉卡,其实实际上还是很流畅的。
WindowWindow即窗⼝,是个抽象类,具体实现就是PhoneWindow,对就是那个装着DecorView的PhoneWindow。
Window整体分三种类型:应⽤Window、⼦Window、系统Window。
应⽤Window:对应⼀个Activity⼦Window:不能单独存在,它需要附属在特定的⽗Window中,⽐如常见的⼀些Dialog就是⼦Window。
系统Window:需要声明权限才能⽤,Toast就是⼀种系统Window。
每种Window类型⼜能分多个层级:层级⾼的Window会覆盖层级低的Window,跟Android5.0引⼊的Z轴类似。
权限Android6.0以上,如果要⽤系统Window,我们需要申请悬浮窗权限。
毕竟youtParams.TYPE_TOAST权限限制太多了。
Manifests:<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />判断是否有悬浮窗权限:Settings.canDrawOverlays(this)申请权限:Intent intent = new Intent();intent.setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);intent.setData(Uri.parse("package:"+getPackageName()));startActivity(intent);WindowManagerView想要呈现出来,必须要通过Window,但是我们⽆法直接操作Window,需要⽤到WindowManager。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
大家对悬浮窗概念不会陌生,相信每台电脑桌面的右上角都会有这么一个东西,它总是出现在所有页面的顶端(Top Show)。
但在Android 平台中如何实现这样的效果呢?先来看一看效果图。
看见在Google搜索框上面的那个Icon图片了嘛。
下面我就来详细介绍一下在Android平台下悬浮窗口的实现,并让它能够随手指的触摸而移动。
一、实现原理及移动思路调用WindowManager,并设置youtParams的相关属性,通过WindowManager的addView方法创建View,这样产生出来的View根据youtParams属性不同,效果也就不同了。
比如创建系统顶级窗口,实现悬浮窗口效果!然后通过覆写悬浮View中onTouchEvent方法来改变youtParams中x和y的值来实现自由移动悬浮窗口。
二、示例代码先来看一看悬浮View的代码,这里用一个ImageView作为演示[java]view plaincopyprint?1.public class MyFloatView extends ImageView {2.private float mTouchStartX;3.private float mTouchStartY;4.private float x;5.private float y;6.7.private WindowManager wm=(WindowManager)getContext().getApplicationContext().getSystemService("window");8.//此wmParams变量为获取的全局变量,用以保存悬浮窗口的属性9.private youtParams wmParams = ((MyApplication)getContext().getApplicationContext()).getMywmParams();10.11.public MyFloatView(Context context) {12.super(context);13.// TODO Auto-generated constructor stub14.}16.@Override17.public boolean onTouchEvent(MotionEvent event) {18.//获取相对屏幕的坐标,即以屏幕左上角为原点19.x = event.getRawX();20.y = event.getRawY()-25; //25是系统状态栏的高度21.Log.i("currP", "currX"+x+"====currY"+y);22.switch (event.getAction()) {23.case MotionEvent.ACTION_DOWN: //捕获手指触摸按下动作24.//获取相对View的坐标,即以此View左上角为原点25.mTouchStartX = event.getX();26.mTouchStartY = event.getY();27.Log.i("startP", "startX"+mTouchStartX+"====startY"+mTouchStartY);28.break;29.30.case MotionEvent.ACTION_MOVE: //捕获手指触摸移动动作31.updateViewPosition();32.break;33.34.case MotionEvent.ACTION_UP: //捕获手指触摸离开动作35.updateViewPosition();36.mTouchStartX=mTouchStartY=0;37.break;38.}39.return true;40.}41.42.private void updateViewPosition(){43.//更新浮动窗口位置参数44.wmParams.x=(int)( x-mTouchStartX);45.wmParams.y=(int) (y-mTouchStartY);46.wm.updateViewLayout(this, wmParams); //刷新显示47.}48.49.}上面的wmParams变量(即youtParams)的存储采用了extends Application的方式来创建全局变量,示例代码如下:[java]view plaincopyprint?1.public class MyApplication extends Application {2.3./**4.* 创建全局变量5.* 全局变量一般都比较倾向于创建一个单独的数据类文件,并使用static静态变量7.* 这里使用了在Application中添加数据的方法实现全局变量8.* 注意在AndroidManifest.xml中的Application节点添加android:name=".MyApplication"属性9.*10.*/11.private youtParams wmParams=new youtParams();12.13.public youtParams getMywmParams(){14.return wmParams;15.}16.}再来看一看Activity中的代码:[java]view plaincopyprint?1.public class MyFloatViewActivity extends Activity {2./** Called when the activity is first created. */3.4.private WindowManager wm=null;5.private youtParams wmParams=null;6.7.private MyFloatView myFV=null;8.9.@Override10.public void onCreate(Bundle savedInstanceState) {11.super.onCreate(savedInstanceState);12.setContentView(yout.main);13.//创建悬浮窗口14.createView();15.16.}17.18.private void createView(){19.myFV=new MyFloatView(getApplicationContext());20.myFV.setImageResource(R.drawable.icon); //这里简单的用自带的Icom来做演示21.//获取WindowManager22.wm=(WindowManager)getApplicationContext().getSystemService("window");23.//设置LayoutParams(全局变量)相关参数24.wmParams = ((MyApplication)getApplication()).getMywmParams();25.26./**27.*以下都是youtParams的相关属性28.* 具体用途可参考SDK文档29.*/30.wmParams.type=LayoutParams.TYPE_PHONE; //设置window type31.wmParams.format=PixelFormat.RGBA_8888; //设置图片格式,效果为背景透明32.33.//设置Window flag34.wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL35.| LayoutParams.FLAG_NOT_FOCUSABLE;36./*37.* 下面的flags属性的效果形同“锁定”。
38.* 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。
39.wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL40.| LayoutParams.FLAG_NOT_FOCUSABLE41.| LayoutParams.FLAG_NOT_TOUCHABLE;42.*/43.44.wmParams.gravity=Gravity.LEFT|Gravity.TOP; //调整悬浮窗口至左上角,便于调整坐标45.//以屏幕左上角为原点,设置x、y初始值46.wmParams.x=0;47.wmParams.y=0;48.49.//设置悬浮窗口长宽数据50.wmParams.width=40;51.wmParams.height=40;52.53.//显示myFloatView图像54.wm.addView(myFV, wmParams);55.56.}57.58.@Override59.public void onDestroy(){60.super.onDestroy();61.//在程序退出(Activity销毁)时销毁悬浮窗口62.wm.removeView(myFV);63.}64.}最后,别忘了在AndroidManifest.xml中添加权限:[html]view plaincopyprint?1.<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW">2.</uses-permission>这样一个可以置顶显示、悬浮、且可自由移动的窗口就完工了。
运行一下,然后按Home键返回桌面试试看(不能点击返回键,演示程序这里设置了销毁窗体)三、一些说明WindowManager的方法很简单,基本用到的就三个addView,removeView,updateViewLayout。
而youtParams的属性就多了,非常丰富,这个也是关键所在。
这里例举两个window type:[java]view plaincopyprint?1./**2.* Window type: phone. These are non-application windows providing3.* user interaction with the phone (in particular incoming calls).4.* These windows are normally placed above all applications, but behind5.* the status bar.6.*/7.public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;8.9./**10.* Window type: system window, such as low power alert. These windows11.* are always on top of application windows.12.*/13.public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;可以看出TYPE_SYSTEM_ALERT的显示层次比TYPE_PHONE还要高,有兴趣的可以试一试显示效果哦!另外关键的window flag:[java]view plaincopyprint?1./** Window flag: this window won't ever get focus. */2.public static final int FLAG_NOT_FOCUSABLE = 0x00000008;3.4./** Window flag: this window can never receive touch events. */5.public static final int FLAG_NOT_TOUCHABLE = 0x00000010;6.7./** Window flag: Even when this window is focusable (its8.* {@link #FLAG_NOT_FOCUSABLE is not set), allow any pointer events9.* outside of the window to be sent to the windows behind it. Otherwise10.* it will consume all pointer events itself, regardless of whether they11.* are inside of the window. */12.public static final int FLAG_NOT_TOUCH_MODAL = 0x00000020;最后,关于Android平台下的悬浮窗口,有人说很不友好,有人很困惑哪里会用到。