使用悬浮窗居中的问题 -- 有效果图

 

今天写了个全局可以弹出的悬浮窗来显示重要提示,结果自己把自己绕进去了,一直居中不生效,最后恍然大悟,是全屏状态下背景是透明的,都全屏铺满了,还咋居中啊,解决方法是内部在套一层布局,随便指定位置即可 ,另外这里的文字可以自动滚动显示,下面是截图和关键代码:

效果图:

布局文件:关键是第二个RelativeLayout 的 android:layout_centerInParent="true" 调整这个RelativeLayout的位置 可以改变截图中

弹出框的位置

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll_root"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:layout_centerInParent="true"
        android:layout_width="1030dp"
        android:layout_height="540dp"
        android:background="#000000">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="58dp"
            android:layout_marginTop="35dp"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="32dp"
                android:layout_height="32dp"
                android:background="@drawable/ic_launcher" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="12dp"
                android:text="紧急通知"
                android:textColor="#fd1963"
                android:textSize="24dp" />

        </LinearLayout>

        <com.star.alarm.view.AutoScrollView
            android:id="@+id/message_window_autoscrollview"
            android:layout_width="910dp"
            android:layout_height="390dp"
            android:layout_marginLeft="60dp"
            android:layout_marginTop="105dp"
            android:layout_marginRight="60dp">

            <TextView
                android:id="@+id/message_window_textView"
                android:layout_width="910dp"
                android:layout_height="390dp"
                android:focusable="false"
                android:gravity="left"
                android:text="Hello World!\n\nHello World!\n\nHello World!\n\nHello World!\n\nHello World!\n\nHello World!\n\nHello World!\n\nHello World!\n\nHello World!\n\nHello World!\n\nHello World!"
                android:textColor="#f0f0f0"
                android:textSize="19dp" />
        </com.star.alarm.view.AutoScrollView>
    </RelativeLayout>


</RelativeLayout>

 Window 窗口相关:

import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

import com.star.alarm.R;
import com.star.alarm.constant.AlarmConstant;
import com.star.alarm.dto.MessageDTO;
import com.star.alarm.util.WindowHelper;
import com.star.star_common.StarCommon;
import com.star.star_common.constants.StarCoreVariable;
import com.star.star_common.util.LogUtil;
import com.star.star_common.util.ToastUtil;

import java.util.List;

import static android.content.Context.WINDOW_SERVICE;

public class MessageWindowManager {

    private static volatile MessageWindowManager instance;

    private WindowManager windowManager;
    private View view;
    private AutoScrollView message_window_autoscrollview;
    private TextView message_window_textView;

    private MessageWindowManager() {
    }

    public static MessageWindowManager getInstance() {
        if (instance == null) {
            synchronized (MessageWindowManager.class) {
                if (instance == null) {
                    instance = new MessageWindowManager();
                }
            }
        }
        return instance;
    }

    /**
     * 隐藏消息窗口
     */
    public void hide() {
        if (view != null && windowManager != null) {
            try {
                windowManager.removeView(view);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 展示消息窗口
     */
    public void show(Context context) {
        hide(); 

        windowManager = (WindowManager)context.getSystemService(WINDOW_SERVICE);
        initUI(context);
    }

    /*
     * 初始化控件
     *
     * */
    private void initUI(Context context) {
        try {
            view = LayoutInflater.from(context).inflate(R.layout.message_window, null);
            message_window_autoscrollview = view.findViewById(R.id.message_window_autoscrollview);
            message_window_textView = view.findViewById(R.id.message_window_textView);

            message_window_autoscrollview.setAutoToScroll(true);//设置可以自动滑动
            message_window_autoscrollview.setFistTimeScroll(2000);//设置第一次自动滑动的时间
            message_window_autoscrollview.setScrollRate(200);//设置滑动的速率
            message_window_autoscrollview.setScrollLoop(true);//设置是否循环滑动

            message_window_autoscrollview.setScanScrollChangedListener(new AutoScrollView.ISmartScrollChangedListener() {
                @Override
                public void onScrolledToBottom() {
                    ToastUtil.showShortToast("底部");
                }

                @Override
                public void onScrolledToTop() {
                    ToastUtil.showShortToast("顶部");
                }
            });

            //窗口管理
            WindowHelper windowHelper = new WindowHelper();
            windowManager.addView(view, windowHelper.getParams(context));
        } catch (Exception e) {
            e.printStackTrace();
        }
   
    }
}

WindowHelper类: 


import android.graphics.PixelFormat;
import android.view.WindowManager;

public class WindowHelper {

    public WindowManager.LayoutParams getParams(Context context) {
        // 窗体的布局样式
        WindowManager.LayoutParams mLayout = new WindowManager.LayoutParams();
        // 设置窗体显示类型——TYPE_SYSTEM_ALERT(系统提示)
        mLayout.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;

        // 设置窗体焦点及触摸:
        // FLAG_NOT_FOCUSABLE(不能获得按键输入焦点)
        mLayout.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

        // 设置显示的模式
        mLayout.format = PixelFormat.TRANSLUCENT;

        // 设置窗体宽度和高度
        mLayout.width = WindowManager.LayoutParams.MATCH_PARENT;
        mLayout.height = WindowManager.LayoutParams.WRAP_CONTENT;
        //调用此方法会使机顶盒卡死
//        mLayout.horizontalMargin = DensityUtil.dip2px(context, R.dimen.adaptation_60px);

        return mLayout;
    }
}

AutoScrollView:


import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;


/**
 * 自动滚动textview的封装
 * 监听ScrollView滚动到顶部或者底部做相关事件拦截
 */
public class AutoScrollView extends ScrollView {

    private boolean isScrolledToTop = true; // 初始化的时候设置一下值
    private boolean isScrolledToBottom = false;
    private int paddingTop = 0;
    private final int MSG_SCROLL = 10;
    private final int MSG_SCROLL_Loop = 11;
    private boolean scrollAble = false;//是否能滑动

    //三个可设置的属性
    private boolean autoToScroll = true;   //是否自动滚动
    private boolean scrollLoop = false; //是否循环滚动
    private int fistTimeScroll = 5000;//多少秒后开始滚动,默认5秒
    private int scrollRate = 50;//多少毫秒滚动一个像素点

    public AutoScrollView(Context context) {
        this(context, null);
    }

    public AutoScrollView(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
    }

    private ISmartScrollChangedListener mSmartScrollChangedListener;

    /**
     * 定义监听接口
     */
    public interface ISmartScrollChangedListener {
        void onScrolledToBottom(); //滑动到底部

        void onScrolledToTop();//滑动到顶部

    }

    //设置滑动到顶部或底部的监听
    public void setScanScrollChangedListener(ISmartScrollChangedListener smartScrollChangedListener) {
        mSmartScrollChangedListener = smartScrollChangedListener;
    }

    //ScrollView内的视图进行滑动时的回调方法,据说是API 9后都是调用这个方法,但是我测试过并不准确
    @Override
    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
        super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
        if (scrollY == 0) {
            isScrolledToTop = clampedY;
            isScrolledToBottom = false;
        } else {
            isScrolledToTop = false;
            isScrolledToBottom = clampedY;//系统回调告诉你什么时候滑动到底部
        }

        notifyScrollChangedListeners();
    }

    int lastY;

    //触摸事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 记录触摸点坐标
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                // 计算偏移量
                int offsetY = y - lastY;
                // 在当前left、top、right、bottom的基础上加上偏移量
                paddingTop = paddingTop - offsetY / 10;
                //不要问我上面10怎么来的,我大概估算的,正常一点应该是7或8吧,我故意让手动滑动的时候少一丢
                scrollTo(0, paddingTop);
                break;
        }
        return true;
    }


    //ScrollView内的视图进行滑动时的回调方法,据说是API 9前都是调用这个方法,我新版的SDK也是或回调这个方法
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);

//        if (android.os.Build.VERSION.SDK_INT < 9) {  // API 9及之后走onOverScrolled方法监听,
        if (getScrollY() == 0) {
            isScrolledToTop = true;
            isScrolledToBottom = false;
        } else if (getScrollY() + getHeight() - getPaddingTop() - getPaddingBottom() == getChildAt(0).getHeight()) {
            isScrolledToBottom = true;
            isScrolledToTop = false;
        } else {
            isScrolledToTop = false;
            isScrolledToBottom = false;
        }
        notifyScrollChangedListeners();
//        }

    }

    //判断是否滑动到底部或顶部
    private void notifyScrollChangedListeners() {
        if (isScrolledToTop) {
            if (mSmartScrollChangedListener != null) {
                mSmartScrollChangedListener.onScrolledToTop();
            }
        } else if (isScrolledToBottom) {
            mHandler.removeMessages(MSG_SCROLL);
            if (!scrollLoop) {
                scrollAble = false;
            }
            if (scrollLoop) {
                mHandler.sendEmptyMessageDelayed(MSG_SCROLL_Loop, fistTimeScroll);
            }
            if (mSmartScrollChangedListener != null) {
                mSmartScrollChangedListener.onScrolledToBottom();
            }
        }
    }

    //handler
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MSG_SCROLL:
                    if (scrollAble && autoToScroll) {
                        scrollTo(0, paddingTop);
                        paddingTop += 1;
                        mHandler.removeMessages(MSG_SCROLL);
                        mHandler.sendEmptyMessageDelayed(MSG_SCROLL, scrollRate);
                    }
                    break;
                case MSG_SCROLL_Loop:
                    paddingTop = 0;
                    autoToScroll = true;
                    mHandler.sendEmptyMessageDelayed(MSG_SCROLL, fistTimeScroll);

            }

        }
    };

    //获取子View和ScrollView的高度比较,决定是否能够滑动View
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        View childAt = getChildAt(0);
        int childMeasuredHeight = childAt.getMeasuredHeight(); //获取子控件的高度
        int measuredHeight = getMeasuredHeight();//获取ScrollView的高度
//        Log.e("onMeasure", "childMeasuredHeight:" + childMeasuredHeight + "  ,measuredHeight:" + measuredHeight);
        if (childMeasuredHeight > measuredHeight) {  //如果子控件的高度大于父控件才需要滚动
            scrollAble = true;
            paddingTop = 0;
            mHandler.sendEmptyMessageDelayed(MSG_SCROLL, fistTimeScroll);

        } else {
            scrollAble = false;
        }
    }

    //设置是否自动滚动
    public void setAutoToScroll(boolean autoToScroll) {
        this.autoToScroll = autoToScroll;
    }

    //设置第一次开始滚动的时间
    public void setFistTimeScroll(int fistTimeScroll) {
        this.fistTimeScroll = fistTimeScroll;
        mHandler.removeMessages(MSG_SCROLL);
        mHandler.sendEmptyMessageDelayed(MSG_SCROLL, fistTimeScroll);
    }

    //设置滚动的速率,多少毫秒滚动一个像素点
    public void setScrollRate(int scrollRate) {
        this.scrollRate = scrollRate;
    }

    //设置是否循环滚动
    public void setScrollLoop(boolean scrollLoop) {
        this.scrollLoop = scrollLoop;
    }

}

 最后在希望弹出窗的位置调用:

MessageWindowManager.getInstance().show("传入context 可以是application的");

即可弹出窗。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要让el-select显示悬浮窗,可以使用el-cascader组件,它可以实现级联选择,也可以显示悬浮窗。具体实现方法如下: 1. 在el-select中使用el-cascader组件,设置options属性为一个数组,数组中每个元素为一个对象,该对象包含label和value属性,分别表示选项的文本和值。 2. 设置el-cascader的show-all-levels属性为true,这样就可以显示悬浮窗。 3. 设置el-cascader的expand-trigger属性为'hover',这样就可以在鼠标悬停时展开悬浮窗。 例如,以下代码实现了一个带有悬浮窗的el-select: ``` <template> <el-select v-model="value" placeholder="请选择"> <el-cascader :options="options" :show-all-levels="true" :expand-trigger="'hover'" ></el-cascader> </el-select> </template> <script> export default { data() { return { value: '', options: [ { value: 'zhinan', label: '指南', children: [ { value: 'shejiyuanze', label: '设计原则', children: [ { value: 'yizhi', label: '一致', }, { value: 'fankui', label: '反馈', }, { value: 'xiaolv', label: '效率', }, { value: 'kekong', label: '可控', }, ], }, { value: 'daohang', label: '导航', children: [ { value: 'cexiangdaohang', label: '侧向导航', }, { value: 'dingbudaohang', label: '顶部导航', }, ], }, ], }, { value: 'zujian', label: '组件', children: [ { value: 'basic', label: 'Basic', children: [ { value: 'layout', label: 'Layout 布局', }, { value: 'color', label: 'Color 色彩', }, { value: 'typography', label: 'Typography 字体', }, { value: 'icon', label: 'Icon 图标', }, { value: 'button', label: 'Button 按钮', }, ], }, { value: 'form', label: 'Form', children: [ { value: 'radio', label: 'Radio 单选框', }, { value: 'checkbox', label: 'Checkbox 多选框', }, { value: 'input', label: 'Input 输入框', }, { value: 'input-number', label: 'InputNumber 计数器', }, { value: 'select', label: 'Select 选择器', }, { value: 'cascader', label: 'Cascader 级联选择器', }, ], }, ], }, ], }; }, }; </script> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值