视图以visibility ='GONE'开头。当视图设置为可见时,我希望它下面的所有内容都向下移动该视图的高度。它不是第一次工作,但在此之后每次都有效。
我正在使用一个有三种传送选项的广播组。
如果用户点击第三个选项,则第二个广播组会显示更多选项。
第二个无线电组仅在选择第一个无线电组的第三个选项时可见。当它变得可见时,我希望它下面的一切都向下滑动以腾出空间。我添加了view.animate()。translationY()调用两个无线电组下面的每个视图。这可以在第二个无线电组出现时将所有东西移开,并在它消失时将它们向后滑动。问题是这只能在第二次工作。无线电组第一次出现时,所有视图都保持不变。
SystemClock - 我尝试添加SystemClock.sleep(1500)调用。这只会给动画添加一个延迟,但它仍然无法在第一次工作。
处理程序 - 我尝试添加处理程序来处理动画视图,同样的问题。
启动延迟 - 我尝试按照in this stack-overflow answer和this one
硬编码高度 - 我已经尝试过硬编码距离向下移动。我认为问题可能是我通过在设置为可见之后调用无线电组上的getHeight()来获得高度toMove。如果这是问题,我虽然硬编码高度可能会起作用,但同样的问题仍然存在。
垂直链 - 我尝试将所有视图附加到垂直链中,并在链变得可见时将其添加到链中。当可见性为'GONE'时,无线电组不能包含在链中,将其添加到链中什么也没做。如果在将可见性设置为“VISIBLE”后将其添加到Constraint Layout,则应用程序崩溃。
这是我第一次点击单选按钮时发生的情况: 显示screenshot:广播组,视图不会向下滑动
当我点击最后一个单选按钮时会发生这种情况: screenshot:无线电组2消失了
当我选择“标准交付”之后会发生这种情况,以及我第一次想要发生的事情: screenshot:广播组2设置为可见,其他视图向下滑动
GitHub:This is the whole app GitHub:The specific java file -- radio group switch starts on 109
--- Switch Statement ---
...
...
case R.id.standard_delivery_radio:
delivery = STD_DELIVERY;
deliveryType = "Standard Delivery";
stdDeliveryGroup.setVisibility(View.VISIBLE);
break;
}
// Move the views down
if (stdDeliveryGroup.getVisibility() == View.VISIBLE) {
toMove = stdDeliveryGroup.getHeight(); }
// Move the views back to starting position
if (stdDeliveryGroup.getVisibility() == View.GONE) {
toMove = 0;}
// Animate the Views
shippingNumber.animate().translationY(toMove);
shippingText.animate().translationY(toMove);
orderButton.animate().translationY(toMove);
totalText.animate().translationY(toMove);
totalNumber.animate().translationY(toMove);
如果要在文件中找到代码,请在java / com / example / OrderScreenFragment.java下
我真的环顾四周,找不到为什么会这样,请不要标记为重复或模糊。如果您需要澄清任何内容,我将很乐意澄清。
答案 0 :(得分:2)
<强>更新强>
当首次显示标记为gone
的无线电组的布局时,由于gone
窗口小部件没有高度(或者可能没有),因此无线电组的高度已经测量为零测量,因为它是gone
无论如何)。因此,当您引用其高度时,toMove
变为零。现在,无线电组可见,Android会对其进行测量并将其解决。不幸的是,自toMove == 0
以来,无线电组不会改变。 (使用getHeight()
捕获高度后进行测量和布局。)
当无线电组再次标记为gone
,然后标记为visible
时,toMove
会获得无线电组的高度,因为之前已经过测量并存储了这些测量值。有关详细信息,请参阅"How Android Draws View"。
要解决此问题,您需要明确测量无线电组。我对以下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()
。
constraintLayout.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
constraintLayout.getViewTreeObserver().removeOnPreDrawListener(this);
stdDeliveryGroup.setVisibility(View.GONE);
return false;
}
});
纠正这个问题的另一种方法,也许是最好的方法是稍微修改你的布局。将要向下滑动的小部件的顶部限制在gone
无线电组的底部。您现在可以使用ConstraintSet
和TransitionManager.beginDelayedTransition()
来制作动画。有关简介,请参阅本教程。如果您需要对边距进行一些调整,请查看ConstraintLayout
文档中的Visibility Behavior。
答案 1 :(得分:1)
我最终通过使用visibility =(visible&lt; =&gt; invisible)
来解决问题最初的可见性来自(去掉了&lt; =&gt;可见)。
通过在活动启动时将其设置为“不可见”,我可以测量组的高度,但不会以任何其他方式影响布局。感谢@Cheticamp指出我正确的方向。它确实没有首先测量视图的高度,即使在视图设置为可见之后调用了getHeight()。
前两个答案都不适用于我,他们仍然做同样的事情。对于最后的约束布局建议,我无法将视图的约束附加到设置为“已消失”的视图的底部。
我不知道视图是否“隐形”是理想的解决方案,但它具有预期的效果。如果我将来发现这个方法有任何问题,我会在这里更新。