Как обновить высоту ограниченного представления в ConstraintLayout

У меня есть ConstraintLayout, в котором у меня есть представление (называемое панелью) и RecyclerView, ограниченное нижней частью панели, у RecyclerView высота установлена ​​в соответствии с ограничением (0dp),

Итак, если в редакторе макета Android я перемещаюсь вверх по панели, например, высота RecyclerView увеличивается и всегда «привязана» к панели, это работает,

Но это не то же самое поведение во время выполнения, когда я перемещаю панель (с помощью onTouchListener), высота RecyclerView не меняется вообще и остается, как если бы панель была в том же положении ..

Чтобы добиться этого поведения (переместите панель, увеличьте / уменьшите высоту RecyclerView), я подумал и попытался использовать решение ConstraintLayout,

Итак, я установил ограничение (вверху) для нижней части панели, и я установил высоту, соответствующую ограничению,

Я также пытался добиться такого поведения с помощью LayoutParam, изменяя высоту в зависимости от перемещенных пикселей, но формула не на 100% хороша и, используя этот способ, измените высоту как снизу, так и сверху (по-видимому, не с помощью решения Constraint)

<ConstraintLayout>
...

 <!-- Removed all Constraint to the Bar to let it freely move on Touch on it's Y Axis, also tried to constraint start, end, top to the parent, but same behavior -->
 <include layout="@layout/theBar"
             android:layout_width="match_parent" 
             android:layout_height="wrap_content"
             android:id="@+id/theBarWhoMove"/>

    <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerViewConstrainedToTheBar"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginBottom="2dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="2dp"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginEnd="2dp"
            android:layout_marginTop="8dp"              

        app:layout_constraintTop_toBottomOf="@+id/theBarWhoMove"/>

...
</ConstraintLayout>


barWhoMove.setOnTouchListener { v, event ->

        when(event.actionMasked) {

            MotionEvent.ACTION_DOWN -> {
                barWhoMoveDY = v.y - event.rawY
                return@setOnTouchListener true
            }
            MotionEvent.ACTION_MOVE -> {
                ////We move the Bar
                v.animate().translationY(barWhoMoveDY + 
                event.rawY).setDuration(0).start()

               /* To try to relayout and resize based on match Constrain taking in consideration the new barWhoMove position*/
                recyclerViewConstrainedToTheBar.invalidate()
                recyclerViewConstrainedToTheBar.requestLayout()
                recyclerViewConstrainedToTheBar.forceLayout()

                ////Tried Also
   constraintSet.constrainHeight(recyclerViewConstrainedToTheBar.id, 
ConstraintSet.MATCH_CONSTRAINT)
   constraintSet.applyTo(rootConstraintLayout)

   ////Tried Also
   rootConstraintLayout.invalidate()
   rootConstraintLayout.requestLayout()
   rootConstraintLayout.forceLayout()

                if(v.y < oldDY) {

               /*#Solution 2 increase with LayoutParam but The formula is not 100% correct and it change height from both bottom and top, When View is moving Up or Down(it's work for detecting this)*/

              ....
              oldDy = v.y
                }
                else {
                ....
                oldDy = v.y
                }

                return@setOnTouchListener true
            }
            MotionEvent.ACTION_UP -> {
            }
        }

        return@setOnTouchListener false
    }

Редактировать :

Это содержимое тега <include> в макете 1:

<?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"
    tools:showIn="@layout/fragment_layout_main">

<data>
    <variable name="variable" type="com.demo.ourClass" />
</data>

<android.support.v7.widget.CardView
  android:id="@+id/card"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  app:layout_constraintStart_toStartOf="parent"
  app:layout_constraintTop_toBottomOf="@id/textViewTitle"
  android:layout_marginTop="8dp"
  app:cardElevation="6dp">

  <android.support.constraint.ConstraintLayout 
  android:layout_width="match_parent"                                        
  android:layout_height="match_parent">
  <ImageView
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          app:srcCompat="@mipmap/ic_launcher_round"
          android:id="@+id/imageViewA"
          android:layout_marginTop="8dp"
          app:layout_constraintTop_toTopOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          android:layout_marginStart="8dp"/>
  <TextView
          android:text="@{variable.name}"
          tools:text="TextView"
          android:textAppearance="@style/TextAppearance.AppCompat.Light.SearchResult.Title"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:id="@+id/textViewA"
          app:layout_constraintStart_toEndOf="@+id/imageViewA"
          app:layout_constraintBottom_toBottomOf="@id/imageViewA"
          android:layout_marginStart="8dp" 
          android:layout_marginTop="8dp"
          app:layout_constraintTop_toTopOf="parent"/>

  </android.support.constraint.ConstraintLayout>

</android.support.v7.widget.CardView>


person User One    schedule 28.03.2019    source источник


Ответы (1)


Вы анимируете свойство translationY представления. Изменение этого значения переместило представление макет сообщения. Другими словами, макет завершен, затем сделан ход. В результате RecyclerView ограничивается позицией после макета перед переводом. См. setTranslationY (float):

Устанавливает вертикальное положение этого вида относительно его верхнего положения. Это эффективно позиционирует пост-макет объекта в дополнение к тому, куда его поместил макет объекта.

person Cheticamp    schedule 28.03.2019
comment
Спасибо за отличное объяснение. Итак, если я хорошо понимаю, мне нужен способ, который перемещает представление, а затем завершает макет, а не наоборот? Я тоже подумал о чем-то подобном, поэтому я попытался установить view.y = position, чтобы увидеть, изменится ли это что-то, я также пробовал ViewWhoMove.invalidate / requestLayout и т. д., я также пробовал это в прослушивателе обновлений анимации в onAnimationEnd .. - person User One; 28.03.2019
comment
@UserOne Как вы позиционируете панель в ConstraintLayout? Отправьте XML для просмотра. - person Cheticamp; 28.03.2019
comment
Конечно, я отредактировал свой пост, я добавил содержимое тега ‹include›, чтобы переместить этот макет, я получаю ссылку на включение из макета 1 - person User One; 28.03.2019
comment
Обратите внимание на приложение: layout_constraintTop_toBottomOf = @ id / textViewTitle в содержимом макета тега include, если я удалю if, просмотр исчезнет (предполагаемое поведение) - person User One; 28.03.2019
comment
@UserOne У меня нет хорошей картины вашего полного макета. Я могу предложить, если вы хотите переместить полосу, измените ее нижнее поле. Он должен двигаться, а RecyclerView должен следовать за ним и расширяться. (RecyclerView не будет учитывать маржу стержня.) - person Cheticamp; 28.03.2019
comment
Я установил направляющую линию между панелью и RecyclerView, теперь оба ограничены этой направляющей линией, затем во время выполнения я изменяю процент направляющей линии с помощью этого кода: val totalHeight = rootConstraintLayout.measuredHeight guideline.setGuidelinePercent (Math.min (Math.abs ( event.y / totalHeight), 100F)) И вот что я получаю, это выглядит глючно, как будто панель пытается вернуться в исходное положение: streamable.com/153cx (извините за форматирование кода, я не нашел тег ) - person User One; 29.03.2019
comment
Исправлено: guideline.setGuidelinePercent (Math.min (Math.abs (event.y / totalHeight), 100F)) - ›guideline.setGuidelinePercent (Math.min (Math.abs (event.rawY / totalHeight), 100F)), Но я думаю, может быть, ConstraintLayout должен обрабатывать translationY в будущем ..? В любом случае, большое спасибо за вашу большую помощь и объяснения - person User One; 29.03.2019
comment
@UserOne Звучит хорошо. Я не думаю, что люди, работающие над translationY, считают его неисправным, поэтому не ожидаю, что его поведение изменится. ConstraintLayout активно улучшается, так что, возможно, у этой команды будет способ приспособить эту функциональность. - person Cheticamp; 29.03.2019