폴더블용 디자인
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

ConstraintLayout
버전 2.1 버전에서는 사용자를 보호하기 위해
SharedValues
등 폴더블 기기를 관리할 수 있습니다.
ReactiveGuide
및 MotionLayout
의 애니메이션 지원 향상
공유 값
ConstraintLayout
에 런타임 값을 삽입하는 새로운 메커니즘을 추가했습니다.
시스템 전체 값에 사용하기 위한 것입니다.
ConstraintLayout
에서 값에 액세스할 수 있습니다.
폴더블 기기의 컨텍스트에서는 이 메커니즘을 사용하여
런타임 시 스크롤 없이 볼 수 있는 부분:
Kotlin
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold)
자바
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold);
맞춤 도우미에서 다음 객체의 리스너를 추가하여 공유 값에 액세스할 수 있습니다.
모든 변경사항:
Kotlin
val sharedValues: SharedValues = ConstraintLayout.getSharedValues()
sharedValues.addListener(mAttributeId, this)
자바
SharedValues sharedValues = ConstraintLayout.getSharedValues();
sharedValues.addListener(mAttributeId, this);
FoldableExperiments 예에서
접는 부분을 캡처하는 방법을
Jetpack WindowManager 라이브러리 및 삽입
위치를 ConstraintLayout
로 변환합니다.
Kotlin
inner class StateContainer : Consumer<WindowLayoutInfo> {
override fun accept(newLayoutInfo: WindowLayoutInfo) {
// Add views that represent display features
for (displayFeature in newLayoutInfo.displayFeatures) {
val foldFeature = displayFeature as? FoldingFeature
if (foldFeature != null) {
if (foldFeature.isSeparating &&
foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
) {
// The foldable device is in tabletop mode
val fold = foldPosition(motionLayout, foldFeature)
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold)
} else {
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, 0);
}
}
}
}
}
자바
class StateContainer implements Consumer<WindowLayoutInfo> {
@Override
public void accept(WindowLayoutInfo newLayoutInfo) {
// Add views that represent display features
for (DisplayFeature displayFeature : newLayoutInfo.getDisplayFeatures()) {
if (displayFeature instanceof FoldingFeature) {
FoldingFeature foldFeature = (FoldingFeature)displayFeature;
if (foldFeature.isSeparating() &&
foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL
) {
// The foldable device is in tabletop mode
int fold = foldPosition(motionLayout, foldFeature);
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold);
} else {
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, 0);
}
}
}
}
}
fireNewValue()
는 값을 첫 번째 매개변수로 나타내는 ID를 사용합니다.
두 번째 매개변수로 삽입할 값입니다.
ReactiveGuide

레이아웃에서 SharedValue
를 활용하는 한 가지 방법은
ReactiveGuide
도움이 됩니다. 그러면 기준선에 따라 가로 또는 세로 가이드라인이
SharedValue
에 연결됨
<androidx.constraintlayout.widget.ReactiveGuide
android:id="@+id/fold"
app:reactiveGuide_valueId="@id/fold"
android:orientation="horizontal" />
일반 가이드라인과 동일하게 사용할 수 있습니다.
폴더블용 MotionLayout
MotionLayout
에 모핑에 도움이 되는 여러 기능을 2.1에 추가했습니다.
이는 폴더블에 특히 유용합니다. 일반적으로
애니메이션을 처리해야 합니다.
폴더블에는 두 가지 접근 방식을 사용할 수 있습니다.
- 런타임에 현재 레이아웃 (
ConstraintSet
)을 업데이트하여
접을 수 있습니다.
- 원하는 각 폴더블 상태에 별도의
ConstraintSet
를 사용합니다.
지원 (closed
, folded
또는 fully open
)
ConstraintSet
에 애니메이션 적용
MotionLayout
의 updateStateAnimate()
함수는 2.1에 추가되었습니다.
출시:
Kotlin
fun updateStateAnimate(stateId: Int, set: ConstraintSet, duration: Int)
자바
void updateStateAnimate(int stateId, ConstraintSet set, int duration);
이 함수는 지정된
ConstraintSet
즉시 업데이트(
updateState(stateId, constraintset)
). 이렇게 하면
접을 수 있는 상태와 같은 변화에 따라 즉석에서 조정할 수 있습니다.
MotionLayout
내 ReactiveGuide
ReactiveGuide
는 또한 내부에서 사용할 때 두 가지 유용한 속성을
MotionLayout
:
첫 번째는 현재 ConstraintSet
를 수정하고 변경사항에 애니메이션을 적용합니다.
자동으로 확장 및 축소할 수 있습니다 두 번째는 ReactiveGuide
의 새 값을 적용합니다.
MotionLayout
의 모든 ConstraintSet
에 포지셔닝합니다. 일반적인 접근 방식
폴더블은 접힘 위치를 나타내는 ReactiveGuide
를 사용합니다.
ReactiveGuide
를 기준으로 레이아웃 요소를 설정합니다.
여러 ConstraintSet
를 사용하여 폴더블 상태 표현
현재 MotionLayout
상태를 업데이트하는 대신 설계하는 또 다른 방법
폴더블을 지원하는 UI는 특정한 별도의 상태(
closed
, folded
, fully open
)

이 시나리오에서는 여전히 ReactiveGuide
를 사용하여
자동 스크롤에 비해 더욱 세밀한 관리가 가능합니다.
현재 ConstraintSet
를 업데이트할 때 각 상태가 어떻게 변하는지에 대한 애니메이션
다른 것으로 전환되는 것입니다.
이 방법을 사용하면 DeviceState
리스너에서
MotionLayout
:
MotionLayout.transitionToState(stateId)
메서드를 사용하여 축소하도록 요청합니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-07-27(UTC)"],[],[],null,["# Designing for foldables\n\nIn the [`ConstraintLayout`](/reference/androidx/constraintlayout/widget/ConstraintLayout)\n2.1 release, several features were added to help\nmanage [foldable devices](/guide/topics/ui/foldables), including [`SharedValues`](/reference/androidx/constraintlayout/widget/SharedValues),\n[`ReactiveGuide`](https://github.com/androidx/constraintlayout/blob/d89c45dbb74bf19ad4834198a04af306696357bc/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ReactiveGuide.java), and enhanced support for animation with [`MotionLayout`](/reference/androidx/constraintlayout/motion/widget/MotionLayout).\n\nShared Values\n-------------\n\nWe added a new mechanism to inject runtime values in `ConstraintLayout` --\nthis is intended to be used for system-wide values, as all instances of\n`ConstraintLayout` are able to access the value.\n\nIn the context of foldable devices, we can use this mechanism to inject the\nposition of the fold at runtime: \n\n### Kotlin\n\n```kotlin\nConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold)\n```\n\n### Java\n\n```java\nConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold);\n```\n\nIn a custom helper, you can access the shared values by adding a listener for\nany changes: \n\n### Kotlin\n\n```kotlin\nval sharedValues: SharedValues = ConstraintLayout.getSharedValues()\nsharedValues.addListener(mAttributeId, this)\n```\n\n### Java\n\n```java\nSharedValues sharedValues = ConstraintLayout.getSharedValues();\nsharedValues.addListener(mAttributeId, this);\n```\n\nYou can look at the [FoldableExperiments example](https://github.com/androidx/constraintlayout/blob/main/projects/FoldableExperiments/app/src/main/java/com/example/experiments/MainActivity.kt)\nto see how we capture the position of the fold using the\n[Jetpack WindowManager](/jetpack/androidx/releases/window) library and inject\nthe position into `ConstraintLayout`. \n\n### Kotlin\n\n```kotlin\ninner class StateContainer : Consumer\u003cWindowLayoutInfo\u003e {\n\n override fun accept(newLayoutInfo: WindowLayoutInfo) {\n\n // Add views that represent display features\n for (displayFeature in newLayoutInfo.displayFeatures) {\n val foldFeature = displayFeature as? FoldingFeature\n if (foldFeature != null) {\n if (foldFeature.isSeparating &&\n foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL\n ) {\n // The foldable device is in tabletop mode\n val fold = foldPosition(motionLayout, foldFeature)\n ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold)\n } else {\n ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, 0);\n }\n }\n }\n }\n}\n```\n\n### Java\n\n```java\nclass StateContainer implements Consumer\u003cWindowLayoutInfo\u003e {\n\n @Override\n public void accept(WindowLayoutInfo newLayoutInfo) {\n\n // Add views that represent display features\n for (DisplayFeature displayFeature : newLayoutInfo.getDisplayFeatures()) {\n if (displayFeature instanceof FoldingFeature) {\n FoldingFeature foldFeature = (FoldingFeature)displayFeature;\n if (foldFeature.isSeparating() &&\n foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL\n ) {\n // The foldable device is in tabletop mode\n int fold = foldPosition(motionLayout, foldFeature);\n ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold);\n } else {\n ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, 0);\n }\n }\n }\n }\n}\n```\n\n`fireNewValue()` takes an ID representing the value as the first parameter and\nthe value to inject as the second parameter.\n\n`ReactiveGuide`\n---------------\n\nOne way to take advantage of a `SharedValue` in a layout, without having to\nwrite any code, is to use the [`ReactiveGuide`](https://github.com/androidx/constraintlayout/blob/main/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ReactiveGuide.java)\nhelper. This will position a horizontal or vertical guideline according to the\nlinked `SharedValue`. \n\n \u003candroidx.constraintlayout.widget.ReactiveGuide\n android:id=\"@+id/fold\"\n app:reactiveGuide_valueId=\"@id/fold\"\n android:orientation=\"horizontal\" /\u003e\n\nIt can then be used as a you would with a normal guideline.\n\n`MotionLayout` for foldables\n----------------------------\n\nWe added several features in `MotionLayout` in 2.1 that helps morphing\nstate -- something particularly useful for foldables, as we typically\nhave to handle animating between the different possible layouts.\n\nThere are two approaches available for foldables:\n\n- At runtime, update your current layout (`ConstraintSet`) to show or hide the fold.\n- Use a separate `ConstraintSet` for each of the foldable states you want to support (`closed`, `folded`, or `fully open`).\n\n### Animating a `ConstraintSet`\n\nThe function `updateStateAnimate()` in `MotionLayout` was added in the 2.1\nrelease: \n\n### Kotlin\n\n```kotlin\nfun updateStateAnimate(stateId: Int, set: ConstraintSet, duration: Int)\n```\n\n### Java\n\n```java\nvoid updateStateAnimate(int stateId, ConstraintSet set, int duration);\n```\n\nThis function will automatically animate the changes when updating a given\n`ConstraintSet` instead of doing an immediate update (which you can do with\n`updateState(stateId, constraintset)`). This allows you to update your UI on\nthe fly, depending on changes, such as which foldable state you are in.\n\n### `ReactiveGuide` inside a `MotionLayout`\n\n`ReactiveGuide` also supports two useful attributes when used inside a\n`MotionLayout`:\n\n- `app:reactiveGuide_animateChange=\"true|false\"`\n\n- `app:reactiveGuide_applyToAllConstraintSets=\"true|false\"`\n\nThe first one will modify the current `ConstraintSet` and animate the change\nautomatically. The second one will apply the new value of the `ReactiveGuide`\nposition to all `ConstraintSet`s in the `MotionLayout`. A typical approach for\nfoldables would be to use a `ReactiveGuide` representing the fold position,\nsetting up your layout elements relative to the `ReactiveGuide`.\n\n### Using multiple `ConstraintSet`s to represent foldable state\n\nInstead of updating the current `MotionLayout` state, another way to architect\nyour UI to support foldables is to create specific separate states (including\n`closed`, `folded`, and `fully open`).\n\nIn this scenario, you might still want to use a `ReactiveGuide` to represent the\nfold, but you would have a lot more control (compared to the automated\nanimation when updating the current `ConstraintSet`) on how each state would\ntransition into another.\n\nWith this approach, in your `DeviceState` listener, you would simply direct the\n`MotionLayout` to transition to specific states through the\n[`MotionLayout.transitionToState(stateId)`](/reference/androidx/constraintlayout/motion/widget/MotionLayout#transitionToState(int))\nmethod."]]