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日

相关文章

  • linux桌面卡死怎么重启? linux重启刷新桌面的两种方法

    下面详细讲解一下“linux桌面卡死怎么重启? linux重启刷新桌面的两种方法”。 Linux桌面卡死怎么重启? 当你在使用Linux系统的时候,有时候可能会出现桌面卡死的情况。当我们遇到这种情况时,需要采用一些方法来重启系统。下面介绍两种方法。 方法一:使用命令重启 打开命令行终端,通过CTRL + ALT + T 快捷键或者窗口管理器的菜单打开终端。 …

    other 2023年6月26日
    00
  • 如何正确修改IP地址为手动或自动获取?(只针对局域网ip 静态ip)

    如何正确修改IP地址为手动或自动获取? 在局域网中,我们可以将IP地址设置为手动或自动获取。手动设置IP地址时,我们需要指定一个静态IP地址,而自动获取IP地址时,系统会自动分配一个IP地址给我们的设备。下面是修改IP地址的完整攻略: 1. 打开网络设置 首先,我们需要打开设备的网络设置。这可以通过以下步骤完成: 在Windows上,点击任务栏上的网络图标,…

    other 2023年7月29日
    00
  • my97datepicker日历插件

    当然,我很乐意为您提供有关“my97datepicker日历插件”的完整攻略。以下是详细的步骤和两个示例: 1. 什么是my97datepicker日插件? my97datepicker是一款基于JavaScript的日历插件,可以用于在网页中选择日期。它支持多种日期格式和语,并且可以自定义样式。 以下是my97datepicker的基本语法: <in…

    other 2023年5月6日
    00
  • vue设置路由title,但刷新页面时title失效的解决

    在Vue项目中,如果使用了vue-router进行路由管理,那么设置路由的标题常常是必要的。但是在刷新页面时,路由标题会失效,这是因为刷新页面会重新加载所有资源,包括Vue实例和路由相关的资源。为了解决这个问题,需要进行以下操作: 使用Vue Router的导航守卫 Vue Router提供了导航守卫(navigation guard)来处理路由变化前、后、…

    other 2023年6月27日
    00
  • 关于angularJs指令的Scope(作用域)介绍

    AngularJS指令的Scope介绍 AngularJS是一个流行的JavaScript框架,它使用指令来扩展HTML的功能。指令可以创建新的HTML元素、属性或类,并且可以定义它们的行为和样式。在AngularJS中,每个指令都有一个作用域(Scope),它定义了指令的可见性和数据绑定。 作用域的类型 在AngularJS中,有三种类型的作用域:局部作用…

    other 2023年8月19日
    00
  • C++浅析类与对象的基础

    C++浅析类与对象的基础 在C++中,类是一种用户自定义的数据类型,它是一种封装了数据和函数的实体。对象是类的一个实例,它表示一个具体的个体,可以通过对象来调用类中定义的函数或访问类中定义的数据。 类的定义 类的定义以class关键字开头,后面跟类的名称和类的定义体。类的定义体由类的成员变量和成员函数组成。类的访问修饰符public、private和prot…

    other 2023年6月27日
    00
  • oracle数据库解析json格式

    Oracle数据库可以使用JSON_VALUE、JSON_QUERY、JSON_TABLE等函数来解析JSON格式的数据。以下是使用Oracle数据库解析JSON格式的完整攻略: 首先,创建一个包含JSON格式数据的表。例如,创建一个名为employees的表,其中包含员工的姓名、年龄和工资等信息: sql CREATE TABLE employees ( …

    other 2023年5月9日
    00
  • 贾登峪-景点介绍

    以下是“贾登峪-景点介绍”的完整攻略: 贾登峪-景点介绍 贾登峪位于北京市怀柔区,是一处以自然风光为主的旅游景区。本攻略将详介绍贾登峪的景点,包括贾登峪的位置、门票价格、景点介绍等。 贾登峪的位置 贾登峪于北京市怀柔区,距离北京中心约70里,交通便利。可以乘坐公交车或自驾前往。 贾登峪的门票价格 贾登峪的门价格为60元/人,包含贾登峪景区内的所有景点。 贾登…

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