UI安卓Android深入

Android 悬浮窗实现demo

2021-10-19  本文已影响0人  xq9527

前言:

最近在公司开发手游SDK的时候,需要做一个浮窗功能 虽然网上有各种现成的案例 但是我这边发现很多问题 所以就重新写了一个 不过月还是基于 WindowManager 实现的

效果图:

image.png d1203a5db97a5a5cc2db14a12ccbb801[00_00_03--00_00_23].gif

可以拖拽的悬浮窗 :

    private void initView(){
        if(existView){
            return;
        }
        mScreenWidth = mContext.getResources().getDisplayMetrics().widthPixels;
        mScreenHeigh=mContext.getResources().getDisplayMetrics().heightPixels;
        mManager = (WindowManager) mContext
                .getSystemService(Context.WINDOW_SERVICE);
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.LAST_APPLICATION_WINDOW,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,// FLAG_LAYOUT_NO_LIMITS使x轴可以超出手机屏幕外
                PixelFormat.TRANSLUCENT);
        params.gravity= Gravity.TOP | Gravity.LEFT | Gravity.CENTER_VERTICAL;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        //需要根据横竖屏处理
        params.x=0;
//      params.y=mScreenHeigh/2-100;
        params.y = 100;
        findViewByid(1);
        mHandler.postDelayed(run, 2000);        
    }

@SuppressLint("Range")
    private void findViewByid(int type){
        if(floatView!=null){
            mManager.removeView(floatView);
        }
        if(type==1){
            floatView= LayoutInflater.from(mContext).inflate(ResourceUtil.getLayoutId(mContext, KR.layout.cs_floatview_left), null, false);
            leftLayout=(LinearLayout)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.ll_floatview_left_extends));
            ll_csfloat_hint=(LinearLayout)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.ll_csfloat_hint));
            ll_csfloat_right_hint=(LinearLayout)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.ll_csfloat_right_hint));
        }else{
            floatView= LayoutInflater.from(mContext).inflate(ResourceUtil.getLayoutId(mContext, KR.layout.cs_floatview_right), null, false);
            leftLayout=(LinearLayout)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.ll_floatview_right_extends));
            ll_csfloat_hint=(LinearLayout)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.ll_csfloat_right_hint));
        }
        
        floatView.setAlpha(100);
        imageview=(ImageView)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.iv_floatview_left));
        leftLayout.setVisibility(View.GONE);
        ll_csfloat_hint.setVisibility(View.GONE);
        imageview.setOnTouchListener(new ImageviewOnTouch());
        imageview.getViewTreeObserver().addOnGlobalLayoutListener(
                new OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        mViewWidth = imageview.getWidth();
                        mViewheight=imageview.getHeight();
                        imageview.getViewTreeObserver()
                                .removeGlobalOnLayoutListener(this);
                    }
                });
        mManager.addView(floatView, params);
        setOnClickListener();
        existView=true;
        if(isRegister){
            setTimer();
        }
    }

package com.example.myapplication.drag;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.example.myapplication.KR;
import com.example.myapplication.NineFunSdkGiftbagActivity;
import com.example.myapplication.ResourceUtil;
import java.util.Timer;
import java.util.TimerTask;

/***
 *
 *类说明 :悬浮窗小球
 *
 *
 */

public class CSFloatView {
    
    private Context mContext;
    private View floatView;
    private WindowManager mManager;
    private WindowManager.LayoutParams params;
    private LinearLayout leftLayout,ll_csfloat_hint,ll_csfloat_right_hint;
    private ImageView imageview;
    private int mScreenWidth,mScreenHeigh;
    private boolean isDowned=false;
    private int mViewWidth,mViewheight;
    private static boolean existView=false;
    private TextView mTxtAccount , mTxtService , mTxtGame , mTxtHide ,mfloatHide;
    public static final int ACCOUNT_MANAGER = 0 ;
    public static final int GAME_SERVICE = 1 ;
    public static final int MORE_GAME = 2 ;
    public static final int HIDE_ICON = 3 ;
    public static final int FLOAT_MENU_LAYOUT = 4 ;
    private boolean isRegister=false;
    private boolean timerIsRun=false;
    private Timer timer;
    private boolean isLeft=true;


    
    public CSFloatView(Context context, boolean register) {
        mContext=context;
        isRegister=register;
        initView();
    }

    public void setIsRegister(boolean register){
        isRegister=register;
        if(isRegister){
            setTimer();
        }
    }

    private void initView(){
        if(existView){
            return;
        }
        mScreenWidth = mContext.getResources().getDisplayMetrics().widthPixels;
        mScreenHeigh=mContext.getResources().getDisplayMetrics().heightPixels;
        mManager = (WindowManager) mContext
                .getSystemService(Context.WINDOW_SERVICE);
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.LAST_APPLICATION_WINDOW,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,// FLAG_LAYOUT_NO_LIMITS使x轴可以超出手机屏幕外
                PixelFormat.TRANSLUCENT);
        
        params.gravity= Gravity.TOP | Gravity.LEFT | Gravity.CENTER_VERTICAL;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        //需要根据横竖屏处理
        params.x=0;
//      params.y=mScreenHeigh/2-100;
        params.y = 100;
        findViewByid(1);
        mHandler.postDelayed(run, 2000);        
    }
    
    
    private int initialX;
    private int initialY;
    private float initialTouchX;
    private float initialTouchY;
    private int delay;
    class ImageviewOnTouch implements OnTouchListener {

        @Override
        public boolean onTouch(View view, MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                initialX = params.x;
                initialY = params.y;
                initialTouchX = event.getRawX();
                initialTouchY = event.getRawY();
                mHandler.removeCallbacks(run);
                break;

            case MotionEvent.ACTION_UP:
                
                if(!isDowned){
                    
                    if(Math.abs((event.getRawX() - initialTouchX))>10){
                        
                        Log.e("tag", "移动:"+(event.getRawX() - initialTouchX));
                        if(initialX < 0){
                            params.x = 0 ;
                            mManager.updateViewLayout(floatView, params);
                        }
                        if(initialX > mScreenWidth - mViewWidth ){
                            params.x = mScreenWidth - mViewWidth;
                            mManager.updateViewLayout(floatView, params);
                        }
                        if(params.y<0){
                            params.y=0;
                        }if(params.y+mViewheight>=mScreenHeigh){
                            params.y=mScreenHeigh-mViewheight;
                        }
                        mHandler.postDelayed(run, 2000);
                        
                    }else{

                        params.width=mViewWidth*5;
                        if(params.x>mScreenWidth/2){
                            isLeft=false;
                            findViewByid(0);
                        }else{
                            isLeft=true;
                            if(params.x<0){
                                params.x=0;
                            }
                            findViewByid(1);
                        }
                        delay=params.x;
                        isDowned = false;
                        //弹出菜单界面
                        mContext.startActivity(new Intent(mContext, NineFunSdkGiftbagActivity.class));
                        mManager.updateViewLayout(floatView, params);
                        mHandler.postDelayed(run, 2000);

                    }

                }else{
                    mHandler.removeCallbacks(run);
                    isDowned=false;
                    if(!isLeft){
                        leftLayout.setVisibility(View.GONE);
                    }else{
                        leftLayout.setVisibility(View.GONE);
                        params.width=mViewWidth;
                    }
                    if(delay>=(mScreenWidth-mViewWidth/2)){
                        params.x=mScreenWidth-mViewWidth;
                    }else{
                        params.x=delay;
                    }

                    mManager.updateViewLayout(floatView, params);
                    mHandler.postDelayed(run, 2000);
                }
                

                break;
            case MotionEvent.ACTION_MOVE:
                if(!isDowned){
                    params.x = initialX + (int) (event.getRawX() - initialTouchX);
                    params.y = initialY + (int) (event.getRawY() - initialTouchY);
                    mManager.updateViewLayout(floatView, params);
                }
                break;
            }
            return true;
        }
        
    }

    private void updateView(){

        if(params.x>(mScreenWidth/2)){
            params.x=(mScreenWidth-mViewWidth/3);
            params.alpha = 0.5f;
            mManager.updateViewLayout(floatView, params);
        }else{
            params.x=(mViewWidth/3)-mViewWidth;
            params.alpha = 0.5f;
            mManager.updateViewLayout(floatView, params);
        }
        params.alpha = 1f;
    }
    
    private Handler mHandler=new Handler();
    Runnable run=new Runnable() {
        
        @Override
        public void run() {
            updateView();
        }
    };
    
    @SuppressLint("Range")
    private void findViewByid(int type){
        if(floatView!=null){
            mManager.removeView(floatView);
        }
        if(type==1){
            floatView= LayoutInflater.from(mContext).inflate(ResourceUtil.getLayoutId(mContext, KR.layout.cs_floatview_left), null, false);
            leftLayout=(LinearLayout)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.ll_floatview_left_extends));
            ll_csfloat_hint=(LinearLayout)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.ll_csfloat_hint));
            ll_csfloat_right_hint=(LinearLayout)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.ll_csfloat_right_hint));
        }else{
            floatView= LayoutInflater.from(mContext).inflate(ResourceUtil.getLayoutId(mContext, KR.layout.cs_floatview_right), null, false);
            leftLayout=(LinearLayout)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.ll_floatview_right_extends));
            ll_csfloat_hint=(LinearLayout)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.ll_csfloat_right_hint));
        }
        
        floatView.setAlpha(100);
        imageview=(ImageView)floatView.findViewById(ResourceUtil.getId(mContext, KR.id.iv_floatview_left));
        leftLayout.setVisibility(View.GONE);
        ll_csfloat_hint.setVisibility(View.GONE);
        imageview.setOnTouchListener(new ImageviewOnTouch());
        imageview.getViewTreeObserver().addOnGlobalLayoutListener(
                new OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        mViewWidth = imageview.getWidth();
                        mViewheight=imageview.getHeight();
                        imageview.getViewTreeObserver()
                                .removeGlobalOnLayoutListener(this);
                    }
                });
        mManager.addView(floatView, params);
        setOnClickListener();
        existView=true;
        if(isRegister){
            setTimer();
        }
    }
    
    private void setOnClickListener(){
        mTxtAccount  = (TextView) floatView.findViewById(ResourceUtil.getId(mContext, KR.id.txt_floatmenu_account));
        mTxtService  = (TextView) floatView.findViewById(ResourceUtil.getId(mContext, KR.id.txt_floatmenu_service));
        mTxtGame  = (TextView) floatView.findViewById(ResourceUtil.getId(mContext, KR.id.txt_floatmenu_game));
        mTxtHide  = (TextView) floatView.findViewById(ResourceUtil.getId(mContext, KR.id.txt_floatmenu_hide));
        TextViewOnClick ciickLitener=new TextViewOnClick();
        mTxtAccount.setOnClickListener(ciickLitener);
        mTxtGame.setOnClickListener(ciickLitener);
        mTxtHide.setOnClickListener(ciickLitener);
        mTxtService.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                Toast.makeText(mContext,"客服", Toast.LENGTH_SHORT).show()
            }
        });
        
    }
    
    class TextViewOnClick implements OnClickListener {

        @Override
        public void onClick(View v) {

            Toast.makeText(mContext,""+v.getId(), Toast.LENGTH_SHORT).show();


        }
        
    }
    
    public void hideFloatView(){
        if(mManager!=null&&floatView!=null){
            mHandler.removeCallbacks(run);
//          mManager.removeView(floatView);
            mManager.removeViewImmediate(floatView);
            mManager=null;
            existView=false;
        }

    }

    private void setTimer(){
        if(timerhandler!=null){
            timerhandler.removeMessages(1);
            timerhandler.removeMessages(2);
        }if(timer==null){
            timer=new Timer();
        }else{
            timer.cancel();
            timer=new Timer();
        }
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                timerhandler.sendEmptyMessage(1);
            }
        }, 5000);
    }

    private Handler timerhandler=new Handler(){
        public void handleMessage(Message msg) {
            if(msg.what==1){

                if(leftLayout!=null&&leftLayout.getVisibility()== View.GONE&&ll_csfloat_hint!=null&&ll_csfloat_hint.getVisibility()== View.GONE){

                    ll_csfloat_hint.setVisibility(View.VISIBLE);
                    timerhandler.sendEmptyMessageDelayed(2, 3000);
                    isRegister=false;
                }

            }else if(msg.what==2){
                ll_csfloat_hint.setVisibility(View.GONE);

            }

        };
    };
}

悬浮球布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/ll_csfloat_right_hint"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:paddingRight="10dp"
            android:text="如有问题,在此点客服咨询"
            android:textColor="#FFFFFF"
            android:textSize="13sp" />

    </LinearLayout>

    <ImageView
        android:id="@+id/iv_floatview_left"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:background="@drawable/cs_floatmenu_main" />

    <LinearLayout
        android:id="@+id/ll_csfloat_hint"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        >

        <!--tools:visibility="visible"-->

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:paddingLeft="18dp"
            android:text="如有问题,在此点客服咨询"
            android:textColor="#FFFFFF"
            android:textSize="14sp" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/ll_floatview_left_extends"
        android:layout_width="0dp"
        android:layout_height="60dp"
        android:layout_weight="1"

        android:gravity="center_vertical"
        android:visibility="gone"
        >

        <!--tools:visibility="visible"-->

        <TextView
            android:id="@+id/txt_floatmenu_account"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginLeft="12dp"
            android:layout_weight="1"
            android:gravity="center"
            android:paddingBottom="4dp"
            android:paddingTop="4dp"
            android:text="账号"
            android:textAppearance="?android:attr/textAppearanceSmall"

            android:textColor="#FFFFFF" />

        <TextView
            android:id="@+id/txt_floatmenu_service"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:paddingBottom="4dp"
            android:paddingTop="4dp"
            android:text="客服"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="#FFFFFF" />

        <TextView
            android:id="@+id/txt_floatmenu_game"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"

            android:gravity="center"
            android:paddingBottom="4dp"
            android:paddingTop="4dp"
            android:text="游戏群"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="#FFFFFF" />

        <TextView
            android:id="@+id/txt_floatmenu_hide"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"

            android:gravity="center"
            android:paddingBottom="4dp"
            android:paddingTop="4dp"
            android:text="隐藏"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="#FFFFFF" />
    </LinearLayout>
</LinearLayout>

布局预览

image.png

具体调用

        findViewById(R.id.show).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                FloatMenuGiftbag floatMenuGiftbag=FloatMenuGiftbag.getInstance();
                floatMenuGiftbag.showFloatMenu(context);
                FloatMenuManager.getInstance().showFloatMenu(context);

            }
        });
findViewById(R.id.hide).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                FloatMenuGiftbag floatMenuGiftbag=FloatMenuGiftbag.getInstance();
                floatMenuGiftbag.hideFloatMenu();
                FloatMenuManager.getInstance().hideFloatMenu();

            }
        });

到此我们的悬浮窗效果 就讲完了

最后总结:

整个悬浮窗的效果我们 这边就讲的差不多了 主要是要用官方的 WindowManager 来实现的。我们要注意我们在退出activity要处理好退出逻辑否则会出现下次再次显示崩溃问题 unable to add window 所以在对接游戏的我们注意 这点让游戏直接调用我们退出逻辑

项目地址:

码云 :https://gitee.com/qiuyu123/floatdemo.git

上一篇下一篇

猜你喜欢

热点阅读