Android fragments view.animate()不';第一次不工作,但以后会工作 总结:

Android fragments view.animate()不';第一次不工作,但以后会工作 总结:,android-fragments,visibility,slide,visible,android-constraintlayout,Android Fragments,Visibility,Slide,Visible,Android Constraintlayout,视图以可见性='GONE'开始。当视图设置为可见时,我希望它下面的所有内容都向下移动该视图的高度。第一次不起作用,但之后每次都起作用 说明: 我用的是一个广播组,它有三种传送方式 如果用户单击第三个选项,则会出现第二个收音机组,其中显示更多选项 仅当选择了第一个收音机组的第三个选项时,第二个收音机组才可见。当它变得可见时,我希望它下面的所有东西都向下滑动以腾出空间。我添加了view.animate().translationY()对两个无线组下面的每个视图的调用。当第二个广播组出现时,它可以将所

视图以可见性='GONE'开始。当视图设置为可见时,我希望它下面的所有内容都向下移动该视图的高度。第一次不起作用,但之后每次都起作用

说明: 我用的是一个广播组,它有三种传送方式

如果用户单击第三个选项,则会出现第二个收音机组,其中显示更多选项

仅当选择了第一个收音机组的第三个选项时,第二个收音机组才可见。当它变得可见时,我希望它下面的所有东西都向下滑动以腾出空间。我添加了view.animate().translationY()对两个无线组下面的每个视图的调用。当第二个广播组出现时,它可以将所有东西移开,当它消失时,将它们滑回原位。问题是,这种方法只在第二次使用时有效。无线电组第一次出现时,所有视图都保持不变

尝试:
  • SystemClock--我尝试添加SystemClock.sleep(1500)呼叫。这只是给动画增加了一个延迟,但第一次仍然不起作用

  • 处理程序——我尝试添加一个处理程序来处理动画视图,同样的问题

  • 启动延迟——我已经尝试添加一个启动延迟,正如前面提到的和这里提到的

  • 硬编码高度——我已经尝试硬编码向下移动的距离。我想问题可能是,在设置为visible后,通过调用无线电组上的getHeight()来获取移动的高度。如果这就是问题所在,我认为硬编码高度可能会奏效,但同样的问题依然存在

  • 垂直链--我尝试将所有视图附加到垂直链中,并在无线组可见时将其添加到链中。当可见性“消失”时,广播组无法包含在链中,将其添加到链中没有任何作用。如果在可见性设置为“可见”后将其添加到约束布局中,应用程序将崩溃

截图: 这是我第一次单击单选按钮时发生的情况: 广播组出现,视图不会向下滑动

这是当我单击远离最后一个单选按钮时发生的情况: 第二组离开了

这是我选择“标准交付”之后发生的事情,也是我第一次想要发生的事情: 收音机组2设置为可见,其他视图向下滑动

代码: GitHub: GitHub:

狙击手: 笔记:
  • 这是在一个片段中发生的
  • 代码位于onCreateView方法内的switch语句中
  • 该片段位于主活动内,主活动具有带选项卡的视图寻呼机
  • 如果要在文件中查找代码,请在java/com/example/OrderScreenFragment.java下查找

  • 我真的环顾四周,找不到发生这种情况的原因,请不要标记为重复或模糊。如果你需要澄清什么,我很乐意澄清

更新 当标记为
gone
的无线电组布局首次出现时,无线电组的高度已测量为零,因为
gone
小部件没有高度(或者,可能只是因为它已
gone
而未测量)。因此,当您参考其高度时,
toMove
变为零。现在无线电组已可见,安卓将对其进行测量并进行布局。不幸的是,由于
toMove==0
,无线电组没有移动。(使用
getHeight()
捕获高度后,会进行测量和布局)

当无线电组再次标记为
消失
,然后标记为
可见
,则
toMove
获取无线电组的高度,因为它是先前测量的,并且存储了这些测量值。有关更多详细信息,请参阅

要解决此问题,需要明确测量无线电组。我已在下面对您的
onCreateView()
进行了更改:

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the Layout for this fragment
        View myView = inflater.inflate(R.layout.fragment_order, container, false);
        constraintLayout = (ConstraintLayout) myView.findViewById(R.id.order_screen_layout);
        set = new ConstraintSet();
        set.clone(constraintLayout);
        set.applyTo(constraintLayout);

        // Radio Groups
        RadioGroup deliveryGroup = (RadioGroup) myView.findViewById(R.id.radioGroup);
        stdDeliveryGroup = (RadioGroup) myView.findViewById(R.id.std_delivery_group);

        deliveryGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // Checked ID is the radio button selected

                switch (checkedId) {
                    case R.id.pickup_radio_button:
                        shipping = 0;
                        delivery = PICKUP;
                        deliveryType = "Pick-Up";
                        updatePrice();
                        stdDeliveryGroup.setVisibility(View.GONE);
                        break;

                    case R.id.free_delivery_radio:
                        shipping = 0;
                        delivery = CBD_DELIVERY;
                        deliveryType = "CBD - Delivery";
                        updatePrice();
                        stdDeliveryGroup.setVisibility(View.GONE);
                        break;

                    case R.id.standard_delivery_radio:
                        // ToDo: Impliment delivery charges if delivering outside of CBD
                        delivery = STD_DELIVERY;
                        deliveryType = "Standard Delivery";
                        stdDeliveryGroup.setVisibility(View.VISIBLE);
//                                SystemClock.sleep(2000);
                        break;
                }

                if (stdDeliveryGroup.getVisibility() == View.VISIBLE) {
                    // Force measurement since view was "gone" at last measurement.
                    if (stdDeliveryGroup.getMeasuredHeight() == 0) {
                        // Only force measurement if the view is gone; otherwise, the normal flow
                        // will work.
                        ViewGroup.LayoutParams lp = stdDeliveryGroup.getLayoutParams();
                        int widthSpec = View.MeasureSpec.makeMeasureSpec(lp.width, View.MeasureSpec.EXACTLY);
                        int heightSpec = View.MeasureSpec.makeMeasureSpec(lp.height, View.MeasureSpec.EXACTLY);
                        stdDeliveryGroup.measure(widthSpec, heightSpec);
                    }
                    toMove = stdDeliveryGroup.getMeasuredHeight();
                }

                if (stdDeliveryGroup.getVisibility() == View.GONE) {
                    toMove = 0;
                }

                shippingNumber.animate().translationY(toMove);
                shippingText.animate().translationY(toMove);
                orderButton.animate().translationY(toMove);
                totalText.animate().translationY(toMove);
                totalNumber.animate().translationY(toMove);
            }
        });

        return myView;
    }

经过思考,我意识到,如果无线组的大小没有以精确的单位指定,那么前面的解决方案就会有问题。最初将无线电组的可见性设置为
visible
的另一种方法。这将导致Android对无线电组进行测量和布局。然后,我们将使用
ConstraintLayout
上的预绘制侦听器中止布局的绘制,并将可见性设置为
gone
。将XML中无线电组的可见性更改为
visible
,并将以下代码添加到
onCreate()


纠正这个问题的另一种方法,也许是最好的方法,就是稍微修改一下布局。约束要向下滑动到
gone
无线电组底部的小部件的顶部。现在可以使用
ConstraintSet
TransitionManager.beginDelayedTransition()
制作动画。有关介绍,请参见本教程。如果需要对页边距进行一些调整,请查看
ConstraintLayout
文档。

解决方案: 我最终通过使用visibility=(visible<=>invisible)解决了这个问题

说明: 最初,可见性从(变为<=>可见)

通过在活动开始时将其设置为“不可见”,我可以测量组的高度,但它不会以任何其他方式影响布局。感谢@Cheticamp为我指明了正确的方向。它确实没有首先测量视图的高度,即使对getHeight()的调用是在视图设置为visible之后进行的

前两个答案对我都不起作用,它们仍然做着同样的事情。对于最后的约束布局建议,我无法将视图的约束附加到设置为“gone”的视图底部

我不知道“看不见”的观点是否是理想的解决方案,但它是有愿望的
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the Layout for this fragment
        View myView = inflater.inflate(R.layout.fragment_order, container, false);
        constraintLayout = (ConstraintLayout) myView.findViewById(R.id.order_screen_layout);
        set = new ConstraintSet();
        set.clone(constraintLayout);
        set.applyTo(constraintLayout);

        // Radio Groups
        RadioGroup deliveryGroup = (RadioGroup) myView.findViewById(R.id.radioGroup);
        stdDeliveryGroup = (RadioGroup) myView.findViewById(R.id.std_delivery_group);

        deliveryGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // Checked ID is the radio button selected

                switch (checkedId) {
                    case R.id.pickup_radio_button:
                        shipping = 0;
                        delivery = PICKUP;
                        deliveryType = "Pick-Up";
                        updatePrice();
                        stdDeliveryGroup.setVisibility(View.GONE);
                        break;

                    case R.id.free_delivery_radio:
                        shipping = 0;
                        delivery = CBD_DELIVERY;
                        deliveryType = "CBD - Delivery";
                        updatePrice();
                        stdDeliveryGroup.setVisibility(View.GONE);
                        break;

                    case R.id.standard_delivery_radio:
                        // ToDo: Impliment delivery charges if delivering outside of CBD
                        delivery = STD_DELIVERY;
                        deliveryType = "Standard Delivery";
                        stdDeliveryGroup.setVisibility(View.VISIBLE);
//                                SystemClock.sleep(2000);
                        break;
                }

                if (stdDeliveryGroup.getVisibility() == View.VISIBLE) {
                    // Force measurement since view was "gone" at last measurement.
                    if (stdDeliveryGroup.getMeasuredHeight() == 0) {
                        // Only force measurement if the view is gone; otherwise, the normal flow
                        // will work.
                        ViewGroup.LayoutParams lp = stdDeliveryGroup.getLayoutParams();
                        int widthSpec = View.MeasureSpec.makeMeasureSpec(lp.width, View.MeasureSpec.EXACTLY);
                        int heightSpec = View.MeasureSpec.makeMeasureSpec(lp.height, View.MeasureSpec.EXACTLY);
                        stdDeliveryGroup.measure(widthSpec, heightSpec);
                    }
                    toMove = stdDeliveryGroup.getMeasuredHeight();
                }

                if (stdDeliveryGroup.getVisibility() == View.GONE) {
                    toMove = 0;
                }

                shippingNumber.animate().translationY(toMove);
                shippingText.animate().translationY(toMove);
                orderButton.animate().translationY(toMove);
                totalText.animate().translationY(toMove);
                totalNumber.animate().translationY(toMove);
            }
        });

        return myView;
    }
constraintLayout.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
    @Override
    public boolean onPreDraw() {
        constraintLayout.getViewTreeObserver().removeOnPreDrawListener(this);
        stdDeliveryGroup.setVisibility(View.GONE);
        return false;
    }
});