android popupwindow调整动画大小不平滑

v64noz0r  于 2021-07-09  发布在  Java
关注(0)|答案(0)|浏览(257)

我在一个自定义弹出窗口,这需要调整大小和拖动窗口的翻译工作。
看起来调整大小是资源密集型的,并且会导致动画中的这种迟钝,请注意窗口调整大小时的右角。
为了再现这个问题,我已经实现了在全屏模式和迷你模式之间的切换,点击窗口现在和github项目和代码复制是附加的。要复制的github项目:https://github.com/ankush38u/inappwindow
代码:
自定义窗口小部件.java

package com.example.inappwindow;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;

import androidx.annotation.NonNull;

import java.util.Timer;
import java.util.TimerTask;

public class CustomWindowWidget extends PopupWindow {

    public static final int LAYOUT_FULL_SCREEN = 1;
    public static final int LAYOUT_HALF_SCREEN = 2;
    public static final int LAYOUT_MINI_SCREEN = 3;
    public static final int LAYOUT_ARROW = 4;
    private static final int ANIMATION_TIME = 1000;
    private static final String TAG = CustomWindowWidget.class.getCanonicalName();
    private Context context;
    private int mPosX = 0, mPosY = 0;
    private Handler handler;
    private int SCREEN_WIDTH;
    private int SCREEN_HEIGHT;
    private int currentLayout;
    private int width = 0;
    private int height = 0;
    private RelativeLayout rootLayout;

    private int frameCount;

    public CustomWindowWidget(@NonNull Context context) {
        super(context);
        this.context = context;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            setElevation(PixelDpConverter.dpToPx(8, context));
        }
        setOutsideTouchable(false);
        setFocusable(false);
        setTouchable(true);
        setClippingEnabled(false);
        handler = new Handler();
        SCREEN_WIDTH = PixelDpConverter.getScreenWidthPixels(context);
        SCREEN_HEIGHT = PixelDpConverter.getScreenHeightPixels(context);
        //setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
    }

    @Override
    public void setContentView(View contentView) {
        super.setContentView(contentView);
    }

    @SuppressLint("ClickableViewAccessibility")
    public void show(View parent, int layout_mode) {
        rootLayout = getContentView().findViewById(R.id.root_layout);
        rootLayout.setOnClickListener(v -> {
            if (currentLayout == LAYOUT_MINI_SCREEN) {
                animate(0, 0, SCREEN_WIDTH / 3, SCREEN_WIDTH, SCREEN_HEIGHT / 3, SCREEN_HEIGHT, LAYOUT_FULL_SCREEN);
            } else if (currentLayout == LAYOUT_FULL_SCREEN) {
                animate(SCREEN_WIDTH - SCREEN_WIDTH / 3, 0, SCREEN_WIDTH, SCREEN_WIDTH / 3, SCREEN_HEIGHT, SCREEN_HEIGHT / 3, LAYOUT_MINI_SCREEN);
            }
        });
        showAtLocation(parent, Gravity.TOP | Gravity.LEFT, mPosX, mPosY); //Solves Android pie bug need to start from 0,0 to start coordinate system from top left
        changeLayoutMode(layout_mode);
    }

    private void changeLayoutMode(int layout) {
        switch (layout) {
            case LAYOUT_FULL_SCREEN:
                mPosX = 0;
                mPosY = 0;
                update(mPosX, mPosY, SCREEN_WIDTH, SCREEN_HEIGHT);
                break;
            case LAYOUT_HALF_SCREEN:
                mPosX = 0;
                mPosY = 0;
                update(mPosX, mPosY, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
                break;
            case LAYOUT_MINI_SCREEN:
                mPosX = SCREEN_WIDTH - SCREEN_WIDTH / 3;
                mPosY = 0;
                update(mPosX, mPosY, SCREEN_WIDTH / 3, SCREEN_HEIGHT / 3);
                break;
        }

        currentLayout = layout;
    }

    private void animate(int toX, int toY, int fromWidth, int toWidth, int fromHeight, int toHeight, int toLayoutMode) {
        AnimatorSet animationSet = new AnimatorSet();
        //ValueAnimator.setFrameDelay(40);
        ValueAnimator anim = ValueAnimator.ofInt(fromWidth, toWidth);
        anim.addUpdateListener(valueAnimator -> {
            int val = (Integer) valueAnimator.getAnimatedValue();
            width = val;
        });
        anim.setDuration(ANIMATION_TIME);

        ValueAnimator anim2 = ValueAnimator.ofInt(fromHeight, toHeight);
        anim2.addUpdateListener(valueAnimator -> {
            int val = (Integer) valueAnimator.getAnimatedValue();
            height = val;
            frameCount++;
        });
        anim2.setDuration(ANIMATION_TIME);

        ValueAnimator anim3 = ValueAnimator.ofInt(mPosX, toX);
        anim3.addUpdateListener(valueAnimator -> {
            int val = (Integer) valueAnimator.getAnimatedValue();
            mPosX = val;
        });
        anim3.setDuration(ANIMATION_TIME);

        ValueAnimator anim4 = ValueAnimator.ofInt(mPosY, toY);
        anim4.addUpdateListener(valueAnimator -> {
            int val = (Integer) valueAnimator.getAnimatedValue();
            mPosY = val;
            handler.post(() -> {
                //width = SCREEN_WIDTH - mPosX; //testing if changing width based on position, as the position changes that much width is increased or decreased, should produce better results?
                Log.d(TAG, "Updated mPosX: " + mPosX + ", mPosY: " + mPosY + ", width: " + width + ", height: " + height);
                update(mPosX, mPosY, width, height);
            });
        });
        anim4.setDuration(ANIMATION_TIME);
        animationSet.play(anim).with(anim2).with(anim3).with(anim4);
        //animationSet.setInterpolator(new AnticipateInterpolator());
        animationSet.cancel();
        frameCount = 0;
        animationSet.start();
        animationSet.setDuration(ANIMATION_TIME);
        animationSet.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                Log.d(TAG, "Number of frames: " + frameCount);
                currentLayout = toLayoutMode;
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });

    }

}

主活动.java

package com.example.inappwindow;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;

import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;

import com.example.inappwindow.databinding.LayoutWindowBinding;

public class MainActivity extends AppCompatActivity {
    private CustomWindowWidget customWindowWidget;
    private LayoutWindowBinding binding;
    private Handler handler;
    private static  final  String TAG = MainActivity.class.getName();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        customWindowWidget = new CustomWindowWidget(MainActivity.this);
        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (inflater != null) {
            binding = DataBindingUtil.inflate(inflater, R.layout.layout_window, null, false);
            customWindowWidget.setContentView(binding.getRoot());
        }

        handler = new Handler();
        handler.postDelayed(() -> {
            View parentView = MainActivity.this.getWindow().getDecorView().getRootView();
            customWindowWidget.show(parentView, CustomWindowWidget.LAYOUT_FULL_SCREEN);
        },500);
    }
}

布局\u window.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <RelativeLayout
        android:id="@+id/root_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center_horizontal"
        android:background="@android:color/transparent"
        android:gravity="center"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:orientation="vertical">

        <LinearLayout
            android:id="@+id/contentPane"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <androidx.appcompat.widget.AppCompatImageView
                android:id="@+id/image_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="fitXY"
                app:srcCompat="@drawable/test"
                tools:ignore="RtlHardcoded" />
        </LinearLayout>
    </RelativeLayout>
</layout>

要复制的github项目:https://github.com/ankush38u/inappwindow
产生的结果:

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题