Android开发(3) 浮动窗口(控件)

关于浮在界面上的可拖动窗口(控件),现在知道的有三种方案。

1.FloatView 

FloatView是指在所有窗口(包括其他Activity,其他程序,桌面)上面的浮动窗口,一些浮动菜单,工具栏,流量监控界面等,github上找了几个例子,似乎需要权限。虽然有些方案说是不需要权限,还没弄明白。

暂时不需要。

2.Dialog

这个就是弹出对话框了,拖动也能做,但是问题是它是和原来的界面分离了,没关闭的情况下无法操作原来的界面。

3.DragView

这个其实就是我需要的,只要把一个控件浮动到另一个控件的上面(具体来说是把webrtc的SurfaceViewRenderer浮动到unity界面的前面,显示摄像头监控视频,并且可以拖动)。

参考:Android之View拖拽效果

基本原型很简单,创建一个新的类,继承某个控件类,修改一下onTouchEvent就行,而且我不是拖动到另一个控件里面,只是需要拖动而已,不需要里面的第二步。

不过,需要继承,耦合度高,而且发现,只有在被拖动控件在左上角才有效,在其他地方,如多个Button的后面几个,会有偏移。经测试发现需要把控件的起始位置记录下来。

另外改成通过Listener方式来解耦。

总之最后写了个Dragger类

package com.shencode.cww.drag;

import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;

public class Dragger {
    private View view;
    private ViewGroup parent;
    private float moveX;
    private float moveY;
    private float localX;
    private float localY;
    private float localZ;
    private static float maxLocalZ=-1;
    private boolean isFirst=true;

    public Dragger(View view,boolean onlyDrag){
        this.view=view;
        this.onlyDrag=onlyDrag;
        ViewTreeObserver vto=view.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
//                showXYZ("Dragger");
                initXYZ();
            }
        });
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return onTouchEvent(v,event);
            }
        });
        ViewParent p=view.getParent();
        if(p instanceof ViewGroup){
            parent=(ViewGroup)p;
        }
        //parent.getch
    }

    private void initXYZ() {
        if (isFirst) {
            localX = view.getX();
            localY = view.getY();
            localZ = view.getZ();
            isFirst = false;
            Log.d("initXYZ", String.format("%s (%s,%s,%s)(%s,%s)", view, view.getX(), view.getY(), view.getZ(), view.getTranslationX(), view.getTranslationY()));
            getMaxZ();
        }
    }

    private void getMaxZ(){
        if(maxLocalZ<0){
            ViewParent p=view.getParent();
            if(p instanceof ViewGroup){
                parent=(ViewGroup)p;
            }
            if (parent != null) {
                for (int i = 0; i < parent.getChildCount(); i++) {
                    View c = parent.getChildAt(i);
                    float z = c.getZ();
                if (z > maxLocalZ) {
                    maxLocalZ = z;
                    Log.d("getMaxZ", "maxLocalZ2:" + maxLocalZ);
                }
                }
            }
        }
    }

    //fasle:可以进行控件的固有操作,但是webrtc的SurfaceViewRenderer不能拖动了。
    //true:只能拖动,button的click事件,checkbox的check事件,editoview的输入功能都没有
    private boolean onlyDrag=true;

    private boolean onTouchEvent(View v,MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                moveX = event.getX()+localX;
                moveY = event.getY()+localY;
                //view.bringToFront();//这个会改变在LinearLayout里面的位置,不行
                v.setZ(maxLocalZ+0.1f);//Z设置太高的话会有阴影
                showXYZ("onTouchEvent");
                break;
            case MotionEvent.ACTION_MOVE:
                v.setTranslationX(v.getX() + (event.getX() - moveX));
                v.setTranslationY(v.getY() + (event.getY() - moveY));
                break;
            case MotionEvent.ACTION_UP:
                v.setZ(localZ);
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
        }
        return onlyDrag;
        //fasle:可以进行控件的固有操作,但是webrtc的SurfaceViewRenderer不能拖动了。
        //true:只能拖动,button的click事件,checkbox的check事件,editoview的输入功能都没有
    }

    private void showXYZ(String tag){
        Log.d(tag,String.format("%s (%s,%s),(%s,%s,%s),(%s,%s)",view,moveX,moveY,view.getX(),view.getY(),view.getZ(),view.getTranslationX(),view.getTranslationY()));
    }

    public static void setDragger(View view,boolean onlyDrag){
        Dragger dragger=new Dragger(view,onlyDrag);
    }
}

使用上可以新建控件,也可以单独使用。

public class DragButton extends AppCompatButton {
    Dragger dragger=new Dragger(this);

    public DragButton(Context context) {
        super(context);
    }

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

    public DragButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}
        Button btnDragTestButton1=findViewById(R.id.btnDragTestButton1);
        Dragger dragger=new Dragger(btnDragTestButton1);
        findViewById(R.id.btnDragButton1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("DragTestActivity","btnDragTestButton1 onClick:"+v);
            }
        });

经过测试,这种方式,什么控件都能拖动,而且也能正常使用(onTouchEvent返回true的话可能是拦截了后续的操作了,控件的交互功能就没有了)。

----------------------------------------------------

另外找到一个ViewDragHelper,参考:Android中神奇的ViewDragHelper

按着创建了一个DragLinearLayout,测试发现DragLinearLayout里面的View和TextView可以拖动,但是里面的Button,CheckBox,EditView等有具体交互功能的控件都不能拖动。

后面有空再研究ViewDragHelper吧,先用我写的Dragger了。

-------------------------------------------------------

对控件的长宽进行调整,或者布局发生变化。

    private void setViewSize(View v, int w, int h){
        ViewGroup.LayoutParams lp=v.getLayoutParams();
        lp.width=w;
        lp.height=h;
        v.setLayoutParams(lp);
    }

可能会导致物体的初始位置发生变化,需要重新设置一下localXYZ。

    public void reInit(){
        isFirst=true;
        initXYZ();
    }

另外加了个reset,恢复初始位置

    public void reset(){
        view.setX(localX);
        view.setY(localY);
        view.setZ(localZ);
    }

--------------------------------------------------------------------------------------------

后来了解到还有其他方式,参考:5分钟搞定PopUpWindowAndroid Popupwindow 拖动

弹窗有很多种实现方式,例如:

Dialog
DialogFragment
Fragment
PopUpWindow
ListPopUpWindow

PopUpWindow更似乎功能需求。

具体看下一篇吧《UnityAndroid(4) Unity上显示窗口

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值