Android仿360悬浮小球自定义view实现示例

下面我将为您详细讲解“Android仿360悬浮小球自定义view实现示例”的完整攻略,过程中将包含两个示例说明。

一、前置知识

在开始实现自定义view之前,需要掌握以下内容:

  1. Android基础知识,如Activity、Fragment、View等的生命周期和使用方法。

  2. 自定义View的基本知识,如View的绘制、事件处理、属性设置等。

  3. Android的动画知识,如属性动画、补间动画等。

  4. 熟练掌握Java编程语言。

二、实现自定义悬浮球

以下将介绍两种实现自定义悬浮球的方式。

  1. 实现方式一

第一步:创建一个自定义的View类,并重写onDraw方法进行悬浮球的绘制。

public class FloatBallView extends View {
    private Paint mPaint;
    private float mBallRadius = 30;

    public FloatBallView(Context context) {
        super(context);
        init();
    }

    public FloatBallView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(mBallRadius, mBallRadius, mBallRadius, mPaint);
    }
}

第二步:在Activity或Fragment中引入自定义View。

public class MainActivity extends AppCompatActivity {
    private FloatBallView mFloatBallView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mFloatBallView = findViewById(R.id.float_ball_view);
    }
}

第三步:实现悬浮球拖拽功能

public class MainActivity extends AppCompatActivity {
    private FloatBallView mFloatBallView;
    private int lastX;
    private int lastY;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mFloatBallView = findViewById(R.id.float_ball_view);
        mFloatBallView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int x = (int) event.getRawX();
                int y = (int) event.getRawY();
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        lastX = x;
                        lastY = y;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        int offsetX = x - lastX;
                        int offsetY = y - lastY;
                        floatBallMove(offsetX, offsetY);
                        lastX = x;
                        lastY = y;
                        break;
                }
                return false;
            }
        });
    }

    private void floatBallMove(int offsetX, int offsetY) {
        int left = mFloatBallView.getLeft() + offsetX;
        int top = mFloatBallView.getTop() + offsetY;
        int right = mFloatBallView.getRight() + offsetX;
        int bottom = mFloatBallView.getBottom() + offsetY;
        mFloatBallView.layout(left, top, right, bottom);
    }
}
  1. 实现方式二

使用WindowManager实现悬浮球

public class FloatWindowManager {
    private static final String TAG = "FloatWindowManager";
    private static volatile FloatWindowManager sInstance;

    private WindowManager mWindowManager;
    private WindowManager.LayoutParams mLayoutParams;
    private FloatBallView mFloatBallView;
    private int mWidth;
    private int mHeight;

    private FloatWindowManager(Context context) {
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        mLayoutParams = new WindowManager.LayoutParams();
        mLayoutParams.format = PixelFormat.TRANSPARENT;
        mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        mLayoutParams.gravity = Gravity.START | Gravity.TOP;
        mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        mFloatBallView = new FloatBallView(context);
        mFloatBallView.setOnTouchListener(new View.OnTouchListener() {
            private int lastX;
            private int lastY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int x = (int) event.getRawX();
                int y = (int) event.getRawY();
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        lastX = x;
                        lastY = y;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        int offsetX = x - lastX;
                        int offsetY = y - lastY;
                        windowMove(offsetX, offsetY);
                        lastX = x;
                        lastY = y;
                        break;
                }
                return false;
            }
        });
        mFloatBallView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(), "点击了悬浮球", Toast.LENGTH_SHORT).show();
            }
        });
    }

    public static FloatWindowManager getInstance(Context context) {
        if (sInstance == null) {
            synchronized (FloatWindowManager.class) {
                if (sInstance == null) {
                    sInstance = new FloatWindowManager(context);
                }
            }
        }
        return sInstance;
    }

    public void show() {
        mWindowManager.addView(mFloatBallView, mLayoutParams);
    }

    public void hide() {
        mWindowManager.removeView(mFloatBallView);
    }

    public void windowMove(int offsetX, int offsetY) {
        mLayoutParams.x += offsetX;
        mLayoutParams.y += offsetY;
        if (Math.abs(mWidth - mLayoutParams.x) < mFloatBallView.getWidth() * 2
                || Math.abs(mLayoutParams.x) < mFloatBallView.getWidth() * 2) {
            hide();
        }
        if (mLayoutParams.y < 0) {
            mLayoutParams.y = 0;
        }
        if (mLayoutParams.y + mFloatBallView.getHeight() > getScreenHeight()) {
            mLayoutParams.y = getScreenHeight() - mFloatBallView.getHeight();
        }
        mWindowManager.updateViewLayout(mFloatBallView, mLayoutParams);
    }

    private int getScreenWidth() {
        return mWindowManager.getDefaultDisplay().getWidth();
    }

    private int getScreenHeight() {
        return mWindowManager.getDefaultDisplay().getHeight();
    }
}

以上就是关于“Android仿360悬浮小球自定义view实现示例”的完整攻略,希望能对您有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android仿360悬浮小球自定义view实现示例 - Python技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • android实现okHttp的get和post请求的简单封装与使用

    下面就为您详细讲解一下“android实现okHttp的get和post请求的简单封装与使用”的攻略。 准备工作 在进行okHttp的get和post请求的封装前,需要先在项目的 build.gradle 文件里添加 okHttp 的依赖: dependencies { implementation ‘com.squareup.okhttp3:okhttp:…

    other 2023年6月25日
    00
  • C语言一维数组初步学习笔记

    C语言一维数组初步学习笔记攻略 什么是一维数组? 在 C 语言中,一维数组是一个有限数量元素的线性数据结构,其中每个元素都具有相同的数据类型并通过一个唯一的索引进行访问。例如,int 类型的一维数组可以包含多个整数,并通过使用索引访问每个整数。 一般地,声明一个一维数组如下所示: int array[SIZE]; 其中 ‘SIZE’ 是数组的大小,整数类型也…

    other 2023年6月25日
    00
  • js向json对象添加值

    当然,我很乐意为您提供JS向JSON对象添加值的攻略。以下是详细的步骤和示例: 步骤1:了解JSON对象 JSON( Object Notation)是一种轻量级的数据交换格式,常用于前后端数据传输。JSON对象由键值对组成,键和之间用冒号分隔,键值对之间用逗号分隔,整个对象用花括号包裹。 步骤2:向JSON对象添加值 以下是向JSON对象添加值的示例: 示…

    other 2023年5月6日
    00
  • Linux常用的磁盘管理及文件目录管理命令总结

    Linux常用的磁盘管理命令总结 磁盘分区和格式化 fdisk 命令:用于对磁盘进行分区操作。 示例: fdisk /dev/sda mkfs 命令:用于对分区进行格式化操作。 示例: mkfs -t ext4 /dev/sda1 磁盘挂载和卸载 mount 命令:用于挂载文件系统。 示例: mount /dev/sda1 /mnt umount 命令:用于…

    other 2023年6月27日
    00
  • css y轴溢出滚动条,x轴溢出显示

    下面是“CSS Y轴溢出滚动条,X轴溢出显示的完整攻略”的详细讲解,包括过程和两个示例等方面。 过程 步骤1:设置元素的宽度和高度 首先需要设置元素的宽度和高度,以便确定元素的大小。可以使用以下CSS代码来设置元素的宽度和高度: .element { width: 300px; height: 200px; } 步骤2:设置元素的溢出属性 接下来需要设置元素…

    other 2023年5月6日
    00
  • arm的strb和ldrb指令分析

    当然,我很乐意为您提供ARM的strb和ldrb指令分析的完整攻略。以下是详细的步骤和示例: 步骤1:了解strb和ldrb指令 strb和ldrb指令是ARM指令集中用于存储和加载8位字节的指令。strb指令用于将一个8位的字节数据存储到内存中,而ldrb指令用于从内存中加载一个8位的字节数据到寄存器中。 步骤2:了解strb和ldrb指令的语法 strb…

    other 2023年5月6日
    00
  • vue页面加载完成再执行的方法

    Vue页面加载完成再执行的方法 在 Vue 应用中,我们有时需要在页面加载完成后再执行某些操作,比如获取数据、执行动画等等。Vue 提供了一些生命周期钩子函数来帮助我们实现这些需求,本篇文章将介绍如何在 Vue 页面加载完成后执行方法。 mounted 钩子函数 mounted 钩子函数是在组件挂载完成后调用的钩子函数,此时组件已经渲染到了页面上并且 DOM…

    其他 2023年3月28日
    00
  • ASP.NET全栈开发教程之在MVC中使用服务端验证的方法

    ASP.NET是一个非常强大的Web开发框架,其中MVC是其中一种常用的模式。在MVC开发中,服务端验证是非常重要的一步,可以防止用户提交无效或恶意数据。 以下是使用服务端验证的步骤: 第一步:在视图中添加表单 <form action="/Home/Index" method="post"> <di…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部