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日

相关文章

  • 这些不常见的域名后缀 你怎么看?

    这些不常见的域名后缀 你怎么看? 简介 在互联网发展的过程中,域名后缀(也称为顶级域名)起到了标识和分类网站的作用。除了常见的域名后缀如.com、.net和.org之外,还存在一些不常见的域名后缀。这些不常见的域名后缀可能提供了更多的选择和个性化的机会,但同时也可能带来一些挑战和风险。 优点 1. 个性化 不常见的域名后缀可以帮助网站在众多网站中脱颖而出,展…

    other 2023年8月5日
    00
  • 电脑资源管理器的右键上下文菜单打不开的两种解决办法

    以下是详细的攻略: 问题描述 在使用电脑资源管理器时,右键点击文件或文件夹,却无法弹出上下文菜单,或者弹出但是无法选中任何项,这是一个常见的问题。 可能原因 第三方程序添加了不兼容的菜单项导致菜单崩溃。 Windows资源管理器文件缓存损坏导致菜单无法正常加载。 解决方案 解决方案1:通过命令重建缓存 点击“开始菜单”,在搜索栏中输入“cmd”并以管理员权限…

    other 2023年6月27日
    00
  • spring的xml文件打开没有namespace等操作选项的解决方案

    针对“spring的xml文件打开没有namespace等操作选项”的问题,我们可以采用以下几个步骤来解决。 步骤1:导入schema文件 在<beans>节点上方加入如下命名空间声明: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 并在<beans>节…

    other 2023年6月26日
    00
  • VUE递归树形实现多级列表

    下面是“VUE递归树形实现多级列表”的完整攻略。 1. 理解递归树形结构 递归树形结构,是指一个树形结构中包含了许多子树,而每个子树中又可能包含有更多的子树,这样的结构就可以使用递归来描述。 2. 实现递归组件 在 Vue 中实现递归树形结构,需要定义一个递归组件。递归组件是指在组件的模板中再次使用相同的组件,从而形成递归结构。 假设我们要实现一个无限级列表…

    other 2023年6月27日
    00
  • Android仿美团外卖菜单界面

    Android仿美团外卖菜单界面攻略 简介 本攻略将详细讲解如何实现一个仿美团外卖菜单界面的Android应用。该应用将包含以下功能:- 展示菜单列表- 添加菜品到购物车- 查看购物车内容- 结算购物车 步骤 步骤一:创建项目 首先,创建一个新的Android项目。可以使用Android Studio来完成这一步骤。 步骤二:设计界面 设计菜单界面需要使用R…

    other 2023年8月20日
    00
  • Android studio怎么初始化设置?

    下面是详细讲解“Android studio怎么初始化设置”的完整攻略及两条示例说明。 Android Studio初始化设置攻略 步骤一:安装Android Studio 首先,需要下载并安装Android Studio。可以从官网https://developer.android.com/studio下载安装文件。 步骤二:创建新项目 安装完成后,打开A…

    other 2023年6月20日
    00
  • IE6,IE7下js动态加载图片不显示错误

    针对IE6、IE7下js动态加载图片不显示的问题,其原因在于浏览器缓存机制的不同导致。在IE6、IE7下,如果通过js动态创建img元素并赋值src属性加载图片,那么图片会被浏览器缓存下来并在后续使用时从缓存中读取。由于IE6、IE7存在缓存机制的限制,导致图片不易被获取。 为解决上述问题,可以采用以下两种方式进行处理: 方式一:添加随机参数 通过添加随机参…

    other 2023年6月25日
    00
  • Android Activity活动页面跳转与页面传值

    Android Activity活动页面跳转与页面传值 在Android开发中,Activity是用户界面的核心组件。当我们需要在不同的Activity之间进行跳转并传递数据时,就需要使用到Activity的跳转和页面传值功能。 1. Activity跳转 在Android中,Activity的跳转可以使用Intent来实现。以下是Activity的跳转步骤…

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