Android View программно setVerticalBias с переходом в ConstraintLayout

Мне нужно вертикально переместить некоторые представления в ConstraintLayout, желательно с эффектом перехода (чтобы избежать «пропуска»).

Макет представляет собой просто макет с ограничениями с несколькими виджетами (без иерархии), все они привязаны к родителю.

Мой файл макета:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:id="@+id/myLayout"
tools:context="com.example.quant.icarus.MainActivity">

<SurfaceView
    android:id="@+id/surfaceView1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

<Button
    android:id="@+id/button1"
    android:layout_width="125dp"
    android:layout_height="48dp"
    android:alpha="0.5"
    android:background="@drawable/button_border"
    android:textColor="@color/ret_text"
    app:layout_constraintVertical_bias="0.97"
    app:layout_constraintHorizontal_bias="0.2"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:text="some text" />

<Button
    android:id="@+id/button2"
    android:layout_width="125dp"
    android:layout_height="48dp"
    android:alpha="0.5"
    app:layout_constraintVertical_bias="0.97"
    app:layout_constraintHorizontal_bias="0.8"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:text="some text" />

<SeekBar
    android:id="@+id/prog_bar"
    android:layout_width="210dp"
    android:layout_height="40dp"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:thumb="@drawable/seekbar_thumb"
    android:max="100"
    android:progress="0"
    android:rotation="270" />

<TextView
    android:id="@+id/prog_text"
    android:layout_width="wrap_content"
    android:layout_height="20dp"
    app:layout_constraintVertical_bias="0.1"
    app:layout_constraintLeft_toLeftOf="@+id/prog_bar"
    app:layout_constraintRight_toRightOf="@+id/prog_bar"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:text="some text"/>

<View
    android:id="@+id/viewToMove1"
    android:layout_width="40dp"
    android:layout_height="1dp"
    app:layout_constraintVertical_bias="0.2"
    app:layout_constraintHorizontal_bias="0.34"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:background="@color/ret_text" />

<View
    android:id="@+id/viewToMove2"
    android:layout_width="40dp"
    android:layout_height="1dp"
    app:layout_constraintVertical_bias="0.35"
    app:layout_constraintHorizontal_bias="0.34"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:background="@color/ret_text" />

<View
    android:layout_width="1dp"
    android:layout_height="30dp"
    app:layout_constraintVertical_bias="0.35"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:background="@color/ret_text" />

<View
    android:layout_width="1dp"
    android:layout_height="30dp"
    app:layout_constraintVertical_bias="0.65"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:background="@color/ret_text" />

</android.support.constraint.ConstraintLayout>

Два представления vewToMove1 и viewToMove2 будут программно перемещены. Однако, когда я пытаюсь сделать следующее, я получаю 2 проблемы. 1) некоторые другие элементы неправильно позиционируются на экране, но виды перемещаются - с пропуском. 2) Если я пробую переход, перемещаемые представления вообще не перемещаются (а другие элементы по-прежнему расположены неправильно.

Вот соответствующий код Java.

public class MainActivity extends AppCompatActivity {

    ConstraintSet cSet = new ConstraintSet();
    ConstraintLayout cLayout;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        }

    @Override
    protected void onResume() {
        super.onResume();

        //Thread which updates views.
        TimerTask move_views = new TimerTask(){
            @Override
            public void run() {

                //some code here...

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {

                        cLayout = (ConstraintLayout) findViewById(R.id.myLayout);//can this be put in onCreate or need to wait until render complete?
                        cSet.clone(cLayout);

                        //TransitionManager.beginDelayedTransition(cLayout);//adding this removes View movement.

                        cSet.setVerticalBias(R.id.viewToMove1,0.43f);//updated in the above thread.
                        cSet.setVerticalBias(R.id.viewToMove2,0.68f);

                        cSet.applyTo(cLayout);

                    }
                });

            }
        };

        Timer move_views_timer = new Timer();
        move_views_timer.scheduleAtFixedRate(move_views,10,10);//time in milliseconds
    }


}

Я не могу понять, почему эта операция затрагивает некоторые другие представления и почему переход не будет работать.

У меня была одна идея: нужно ли ждать завершения загрузки макета (какого-то обратного вызова) перед клонированием ограничений? Как я могу это сделать?


person Antoine Zambelli    schedule 16.08.2017    source источник


Ответы (2)


Никогда не понимал, что не так с исходным подходом, но это сработало для меня (конечно, открыто для более чистых решений):

Animation a = new Animation() {
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        ConstraintLayout.LayoutParams lparams = (ConstraintLayout.LayoutParams) myViewToMove1.getLayoutParams();
        lparams.verticalBias = 0.43f;
        myViewToMove1.setLayoutParams(lparams);
    }
};
a.setDuration(8); // in ms
a.setFillAfter(true);
myViewToMove1.startAnimation(a);

Определите новую анимацию для каждого из представлений. PS: на основе ответа на другой вопрос SO, который я больше не могу найти.

person Antoine Zambelli    schedule 17.08.2017

Итак, после некоторого поиска я нашел ответ, который позволяет вам сделать плавный переход, а также изменить смещение. Ваш ответ частично правильный, но не правильный на 100%.

Сначала вам нужно установить два ограничения, одно из которых будет иметь желаемый эффект, а другое сбросит эти эффекты.

private ConstraintSet applyConstraint=new ConstraintSet();
private ConstraintSet resetConstraint = new ConstraintSet();

Затем вам нужно установить ограничение ConstraintLayout для обоих этих ConstraintSet. Установив ConstraintLayout, я имею в виду поиск его идентификатора и установку его в ConstraintSet.

applyConstraint.clone(constraintLayout);
resetConstraint.clone(constraintLayout);

Затем нужно указать изменения, в нашем примере это настройка смещения по вертикали.

public void applyEffect(){
    TransitionManager.beginDelayedTransition(constraintLayout);//For smooth transition.
    applyConstraint.setVerticalBias(R.id.camera_button,0.43f);
    applyConstraint.applyTo(constraintLayout);
}

Чтобы отменить эффекты, используйте файл resetConstraint.

public void resetEffect(){
    TransitionManager.beginDelayedTransition(constraintLayout);
    resetConstraint.applyTo(constraintLayout);
}
person pratham kesarkar    schedule 21.08.2017