广告
返回顶部
首页 > 资讯 > 移动开发 >Android自定义悬浮按钮效果
  • 607
分享到

Android自定义悬浮按钮效果

2024-04-02 19:04:59 607人浏览 薄情痞子
摘要

本文实例为大家分享了Android自定义悬浮按钮效果的具体代码,供大家参考,具体内容如下 以下:内容没有参考,写的也是一个比较简单的例子,主要就是应用切换前后台时会显示/隐藏悬浮窗。

本文实例为大家分享了Android自定义悬浮按钮效果的具体代码,供大家参考,具体内容如下

以下:内容没有参考,写的也是一个比较简单的例子,主要就是应用切换前后台时会显示/隐藏悬浮窗。内容仅用于自我记录学习使用。

项目开发时应用在登陆后显示一个悬浮窗,同时显示在线人数等一些其他信息,点击悬浮按钮可以显示全局弹窗名单。开发完成后,觉着需要记录一下这种实现方式。所以写一个简单的Demo。
Demo思路是通过启动Service来添加/移除 悬浮窗,因为是一个全局悬浮窗,所以选择依附于Service。
在MyAppliction中监听应用的前后台切换来添加或者隐藏悬浮窗。
其自定义的悬浮窗View在项目中是通过canvas手动绘制的,这里图个省事直接加载一个布局文件。主要是想理解这种添加全局悬浮窗的方式,所以Demo样式和功能能简则简。

MyAppliction


package 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;



public class MyApplication extends Application {
    private Intent mIntent;
    private WindowManager.LayoutParams mFloatingLayoutParams = new WindowManager.LayoutParams();

    public WindowManager.LayoutParams getmFloatingLayoutParams() {
        return mFloatingLayoutParams;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        this.monitorActivityLifecycle();
    }


    
    private void monitorActivityLifecycle() {
        this.reGISterActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

            }

            @Override
            public void onActivityStarted(Activity activity) {
                if (isRunningForeground()){
                    mIntent = new Intent(MyApplication.this, FloatingActionService.class);
                    startService(mIntent);
                }
            }

            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {
                if (!isRunningForeground()){
                    stopService(mIntent);
                }
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

            }

            @Override
            public 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 ---- 悬浮窗所依附的Service


package 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;



public class FloatingActionService extends Service {
    private WindowManager mWindowManager;
    private FloatingActionButton mButton;
    private int mScreenWidth;
    private int mScreenHeight;

    @Override
    public void onCreate() {
        super.onCreate();
        this.initView();
        this.initEvent();

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public 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;

        WindowManager.LayoutParams params = ((MyApplication) this.getApplication()).getmFloatingLayoutParams();
     
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            mFloatingLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            mFloatingLayoutParams.type = WindowManager.LayoutParams.TYPE_TOAST;
        }
        params.format = PixelFormat.RGBA_8888;
        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.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 android.view.LayoutInflater;
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;



public class FloatingActionButton extends FrameLayout {
    private Context mContext;
    private float mStartPointX;
    private float mStartPointY;
    private WindowManager mWindowManager;
    private WindowManager.LayoutParams 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();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    
    private void initView(){
     // 随便添加一个简单的View布局作为悬浮窗
        View view = LayoutInflater.from(mContext).inflate(R.layout.layout_floating_button, null, false);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
        this.addView(view, params);
        this.mWindowManager = (WindowManager) getContext().getApplicationContext().getSystemService(WINDOW_SERVICE);
        this.mFloatingLayoutParams = ((MyApplication) getContext().getApplicationContext()).getmFloatingLayoutParams();
        this.mStatusHeight = getStatusHeight(mContext);

    }

    @Override
    public 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="Http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="@color/colorPrimary">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="12312313131313"
        android:textSize="20sp" />
</LinearLayout>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: Android自定义悬浮按钮效果

本文链接: https://www.lsjlt.com/news/136852.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android自定义悬浮按钮效果
    本文实例为大家分享了Android自定义悬浮按钮效果的具体代码,供大家参考,具体内容如下 以下:内容没有参考,写的也是一个比较简单的例子,主要就是应用切换前后台时会显示/隐藏悬浮窗。...
    99+
    2022-11-12
  • Android仿知乎悬浮功能按钮FloatingActionButton效果
    前段时间在看属性动画,恰巧这个按钮的效果可以用属性动画实现,所以就来实践实践。效果基本出来了,大家可以自己去完善。 首先看一下效果图: 我们看到点击FloatingActio...
    99+
    2022-06-06
    知乎 Android
  • Android利用悬浮按钮实现翻页效果
    今天给大家分享下自己用悬浮按钮点击实现翻页效果的例子。 首先,一个按钮要实现悬浮,就要用到系统顶级窗口相关的WindowManager,WindowManager.Layout...
    99+
    2022-06-06
    按钮 Android
  • Android如何自定义按钮效果
    安卓原生的按钮是多么丑,效果是多么单调,大家也是有目共睹的。 要做一个APP少不了使用按钮,一个好看的按钮少不了好看的效果和外表,这次主要跟大家讲讲如何用drawable的x...
    99+
    2022-06-06
    自定义 按钮 Android
  • Android如何实现自定义可拖拽的悬浮按钮DragFloatingActionButton
    这篇文章主要介绍Android如何实现自定义可拖拽的悬浮按钮DragFloatingActionButton,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!悬浮按钮FloatingActionButton是Androi...
    99+
    2023-05-31
    android
  • 怎么在Android中利用FloatingActionButton实现一个悬浮按钮效果
    今天就跟大家聊聊有关怎么在Android中利用FloatingActionButton实现一个悬浮按钮效果,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。首先是这个最小的Tag:这个T...
    99+
    2023-05-31
    android floatingbutton roi
  • CSS3按钮鼠标悬浮怎么实现光圈效果
    这篇文章主要介绍了CSS3按钮鼠标悬浮怎么实现光圈效果的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇CSS3按钮鼠标悬浮怎么实现光圈效果文章都会有所收获,下面我们一起来看看吧。1 、HTML相关知识点 &nbs...
    99+
    2023-07-04
  • android自定义加减按钮
    本文实例为大家分享了android自定义加减按钮的具体代码,供大家参考,具体内容如下 1、定义两个shape: my_button_shape_normal.xml: <...
    99+
    2022-06-06
    按钮 Android
  • Android自定义控件实现温度旋转按钮效果
    首先看下效果图 温度旋转按钮 实现思路 初始化一些参数 绘制刻度盘 绘制刻度盘下的圆弧 绘制标题与温度标识 绘制旋转按钮 绘制温度 处理滑动事...
    99+
    2022-06-06
    按钮 Android
  • 如何使用CSS3按钮鼠标悬浮实现光圈效果
    小编给大家分享一下如何使用CSS3按钮鼠标悬浮实现光圈效果,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1 、HTML相关知识点...
    99+
    2022-10-19
  • Android自定义RecyclerView Item头部悬浮吸顶
    本文实例为大家分享了Android自定义RecyclerView Item头部悬浮吸顶的具体代码,供大家参考,具体内容如下 概述 1、自定义了一个FrameLayout,引入条目的头...
    99+
    2022-11-12
  • Android ImageButton自定义按钮的按下效果的代码实现方法分享
    使用Button时为了让用户有“按下”的效果,有两种实现方式:1.在代码里面。 代码如下:imageButton.setOnTouchListener(new OnTouch...
    99+
    2022-06-06
    方法 按钮 Android
  • Android自定义ViewGroup实现标签浮动效果
    前面在学习鸿洋大神的一些自定义的View文章,看到了自定义ViewGroup实现浮动标签,初步看了下他的思路以及结合自己的思路完成了自己的浮动标签的自定义ViewGroup。目...
    99+
    2022-06-06
    动效 标签 Android
  • Android自定义View实现开关按钮
     前言:Android自定义View对于刚入门乃至工作几年的程序员来说都是非常恐惧的,但也是Android进阶学习的必经之路,平时项目中经常会有一些苛刻的需求,我们可...
    99+
    2022-06-06
    view 开关 按钮 Android
  • Android自定义覆盖层控件 悬浮窗控件
    在我们移动应用开发过程中,偶尔有可能会接到这种需求: 1、在手机桌面创建一个窗口,类似于360的悬浮窗口,点击这个窗口可以响应(至于窗口拖动我们可以后面再扩展)。 2、自己...
    99+
    2022-06-06
    Android
  • Android滑动组件悬浮固定在顶部效果
    要想实现的效果是如下: 场景:有些时候是内容中间的组件当滑动至顶部的时候固定显示在顶部。 实现的思路: 1.目标组件(button)有两套,放在顶部和内容中间; 2.当内容...
    99+
    2022-06-06
    Android
  • Android view如何实现滑动悬浮固定效果
    这篇文章主要介绍了Android view如何实现滑动悬浮固定效果,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1.背景在项目开发过程中,有时候会碰到这样的需求:在滑动的过程...
    99+
    2023-05-30
    android
  • Android自定义TimeButton实现倒计时按钮
    项目需要要实现一个带有倒计时功能的按钮,其效果类似发送验证码之后在按钮上显示倒计时并且将按钮设置为不可用的功能。 为了项目中其他地方能够调用到,便重写了一个继承于Button的...
    99+
    2022-06-06
    倒计时 按钮 Android
  • Android自定义实现开关按钮代码
    我们在应用中经常看到一些选择开关状态的配置文件,做项目的时候用的是android的Switch控件,但是感觉好丑的样子子 个人认为还是自定义的比较好,先上个效果图: 实...
    99+
    2022-06-06
    开关 按钮 Android
  • Android自定义开关按钮源码解析
    本文实例为大家分享了Android自定义开关的具体代码,供大家参考,具体内容如下 以 ToggleColorY 为例分析, ToggleImageY逻辑代码差不多 初始化参数 获取背...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作