以动画方式将充气的布局/视图移动到新位置

时间:2016-07-27 14:13:07

标签: android android-layout android-animation layout-inflater

我正在给布局充气以在屏幕上显示它。 现在我想将该布局部分移出屏幕。我在膨胀的布局上使用.animate().translationX(-500)尝试了这一点。它完全脱离了屏幕我想要的样子:

之前:

before moving

后:

after moving

但是现在我遇到的问题是布局最初占用的区域是不可点击的(例如,不能在主屏幕之间滑动,只能在蓝色标记区域之外工作)。

not clickable area

如何解决这个问题,移动后可以点击蓝色区域,但布局的红色区域(红色区域)仍然可以记录点击次数(例如,如果我想用onClickListener将其移回)? 我想我必须使用updateViewLayout()的{​​{1}}函数,但我不知道我应该对参数做些什么改变。

修改1:

这是代码。翻译由按钮触发:

overlay.xml

windowManager

夸大布局的服务:

OverlayService.java

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#d8ff0000"
    android:weightSum="1">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="245dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Lorem ipsum "
            android:id="@+id/textView6"
            android:layout_marginLeft="10dp" />

        <Button
            android:layout_width="55dp"
            android:layout_height="wrap_content"
            android:text="X"
            android:id="@+id/button"
            android:layout_gravity="center_horizontal|top"
            android:layout_alignParentTop="true"
            android:layout_toEndOf="@+id/textView6"
            android:layout_marginStart="27dp" />
    </RelativeLayout>
</LinearLayout>

编辑2:

在继续我的研究的同时,我发现public class FloatingMenu extends Service{ private WindowManager wm; private LinearLayout ll; private boolean isPushedToSide = true; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); wm = (WindowManager) getSystemService(WINDOW_SERVICE); ll = new LinearLayout(this); LinearLayout.LayoutParams llParameters = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); ll.setBackgroundColor(Color.argb(50, 255, 255, 255)); ll.setLayoutParams(llParameters); final WindowManager.LayoutParams parameters = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); parameters.gravity = Gravity.LEFT | Gravity.TOP; LayoutInflater li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); ll = (LinearLayout) li.inflate(R.layout.overlay, null); final Button b = (Button) ll.findViewById(R.id.button); b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (isPushedToSide) { ll.animate().translationX(0); isPushedToSide = false; }else { ll.animate().translationX(-450); isPushedToSide = true; } } }); wm.addView(ll, parameters); } } 只移动了渲染视图的位置,而不是视图本身。这也解释了为什么在使用.animate().translationX()后onclick事件仍然会在“移动”布局之前的相同位置被触发。

现在我需要找到一种方法将实际视图与动画结合移动到我想要的位置。任何想法如何做到这一点?

编辑3: 我发现很多帖子都有类似的问题,如果我是对的,问题的解决方案就是使用.animate().translationX()代替ObjectAnimator。 我尝试在代码中替换该部分,以便.animate().translationX()现在看起来像这样:

onClickListener

b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (isPushedToSide) { //ll.animate().translationX(0); ObjectAnimator.ofFloat(ll, "translationX", 0).setDuration(250).start(); isPushedToSide = false; }else { //ll.animate().translationX(-450); ObjectAnimator.ofFloat(ll, "translationX", -450).setDuration(250).start(); isPushedToSide = true; } } }); 是我膨胀的LinearLayout,包含ll文本和Lorem ipsum。 再次,动画本身工作正常,但行为仍然相同。我仍然需要点击按钮的原始位置来触发Button并且蓝色区域仍然无法点击。

编辑4:

正在尝试使用onClickListener更新实际位置的建议。但它没有用。我不确定它是否正确使用它。

.invalidate()

我还尝试更改b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (isPushedToSide) { //ll.animate().translationX(0); ObjectAnimator.ofFloat(ll, "translationX", 0).setDuration(250).start(); ll.invalidate(); isPushedToSide = false; }else { //ll.animate().translationX(-450); ObjectAnimator.ofFloat(ll, "translationX", -450).setDuration(250).start(); ll.invalidate(); isPushedToSide = true; } } }); 的x值并调用LayoutParams,这很正常。当我将叠加层100px向右移动时,触发wm.updateViewLayou(ll, updatedParameters)的区域也会向右推100px。问题是我只能在实际屏幕的边界内移动叠加层,我需要的是将它移出屏幕。绑定负值,但这也不起作用。

我基本上需要的是抽屉导航,但高度有限(至少我认为我需要的是)。要看看我是否能够以这种方式正常工作。

编辑5:

更正了我的代码,以便在动画完成时调用onClickListener,但它的行为方式仍然相同:

ObjectAnimator anim = ObjectAnimator.ofFloat(ll,“translationX”,0).setDuration(250);

.inflate()

我还记录了两个显示问题的.gif文件。我在第二个anim.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) {} @Override public void onAnimationEnd(Animator animator) { b.invalidate(); text.invalidate(); frame.invalidate(); ll.invalidate(); } @Override public void onAnimationCancel(Animator animator) {} @Override public void onAnimationRepeat(Animator animator) {} }); anim.start(); 上设置gravityenter image description here enter image description here

2 个答案:

答案 0 :(得分:0)

我认为解决这个问题的简单方法是动画改变属性&#34;宽度&#34;而是翻译您的布局。

希望有所帮助

答案 1 :(得分:0)

我问过我用来创建这样的SYSTEM_ALERT_WINDOW窗口的指南的创建者,他帮助了我。

以下是代码:

public class Fw  extends Service {

    private WindowManager wm;
    private boolean isPushedToSide = true;


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    WindowManager.LayoutParams parameters;
    Button b;
    View inflating_layout;
    LayoutInflater li;
    ValueAnimator animator;

    @Override

    public void onCreate() {
        super.onCreate();

        wm = (WindowManager) getSystemService(WINDOW_SERVICE);

        li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        inflating_layout = li.inflate(R.layout.overlay, null);

        b = (Button) inflating_layout.findViewById(R.id.button);

        parameters = new WindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, PixelFormat.TRANSLUCENT);
        parameters.gravity = Gravity.LEFT | Gravity.TOP;

        isPushedToSide = true;

        b.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                if (isPushedToSide) {

                    isPushedToSide = false;

                    animator  = ValueAnimator.ofInt(parameters.x, parameters.x-450);
                    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        @Override
                        public void onAnimationUpdate(ValueAnimator valueAnimator) {
                            int val = (Integer) valueAnimator.getAnimatedValue();
                            updateView(inflating_layout, val);

                        }
                    });
                    animator.setDuration(250);
                    animator.start();

                } else {

                    animator = ValueAnimator.ofInt(parameters.x, parameters.x+450);
                    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        @Override
                        public void onAnimationUpdate(ValueAnimator valueAnimator) {
                            int val = (Integer) valueAnimator.getAnimatedValue();
                            updateView(inflating_layout, val);

                        }
                    });
                    animator.setDuration(250);
                    animator.start();


                    isPushedToSide = true;
                }
            }
        });
        wm.addView(inflating_layout, parameters);
    }

    public void updateView(View view, Integer x) {
        if (view != null) {
            if (x != null) parameters.x = x;
            wm.updateViewLayout(view, parameters);
        }
    }
}

现在一切似乎都运转良好。只有滑动动画在屏幕边缘闪烁一点。速度较慢,例如.setDuration(2500)没有发生。我不知道这是因为模拟器还是其他原因。