티스토리 뷰
Stack Overflow에 자주 검색, 등록되는 문제들과 제가 개발 중 찾아 본 문제들 중에서 나중에도 찾아 볼 것 같은 문제들을 정리하고 있습니다.
Stack Overflow에서 가장 먼저 확인하게 되는 가장 높은 점수를 받은 Solution과 현 시점에 도움이 될 수 있는 가장 최근에 업데이트(최소 점수 확보)된 Solution을 각각 정리하였습니다.
아래 word cloud를 통해 이번 포스팅의 주요 키워드를 미리 확인하세요.
How do I make WRAP_CONTENT work on a RecyclerView
RecyclerView에서 WRAP_CONTENT를 사용하려면 어떻게 해야하나요
문제 내용
I have a DialogFragment
that contains a RecyclerView
(a list of cards).
저는 카드 목록인 RecyclerView를 포함하는 DialogFragment를 가지고 있습니다.
Within this RecyclerView
are one or more CardViews
that can have any height.
이 RecyclerView 안에는 높이가 다른 하나 이상의 CardView가 있을 수 있습니다.
I want to give this DialogFragment
the correct height based on the CardViews
that are contained within.
저는 이 DialogFragment의 높이를 포함된 CardView에 기반하여 올바른 높이로 지정하고 싶습니다.
Normally this would be simple, I would set wrap_content
on the RecyclerView
like this.
보통 이것은 간단합니다. 다음과 같이 RecyclerView에 wrap_content를 설정하면 됩니다.
<android.support.v7.widget.RecyclerView ...
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:scrollbars="vertical" >
</android.support.v7.widget.RecyclerView>
Because I am using a RecyclerView
this does not work:
RecyclerView를 사용하기 때문에 이것은 작동하지 않습니다.
https://issuetracker.google.com/issues/37001674
해당 링크는 구글이 관리하는 이슈 트래커 페이지입니다.
and
그리고
Nested Recycler view height doesn't wrap its content
중첩된 리사이클러뷰의 높이가 내용물을 감싸지 않습니다.
On both of these pages people suggest to extend LinearLayoutManager
and to override onMeasure()
이 두 페이지에서는 onMeasure()를 재정의하는 LinearLayoutManager를 확장하는 것을 제안하고 있습니다.
I first used the LayoutManager that someone provided in the first link:
처음에는 첫 번째 링크에서 제공된 LayoutManager를 사용했습니다.
public static class WrappingLayoutManager extends LinearLayoutManager {
public WrappingLayoutManager(Context context) {
super(context);
}
private int[] mMeasuredDimension = new int[2];
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
measureScrapChild(recycler, 0,
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
int width = mMeasuredDimension[0];
int height = mMeasuredDimension[1];
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
case View.MeasureSpec.AT_MOST:
width = widthSize;
break;
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
case View.MeasureSpec.AT_MOST:
height = heightSize;
break;
case View.MeasureSpec.UNSPECIFIED:
}
setMeasuredDimension(width, height);
}
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
View view = recycler.getViewForPosition(position);
if (view != null) {
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
getPaddingLeft() + getPaddingRight(), p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
getPaddingTop() + getPaddingBottom(), p.height);
view.measure(childWidthSpec, childHeightSpec);
measuredDimension[0] = view.getMeasuredWidth();
measuredDimension[1] = view.getMeasuredHeight();
recycler.recycleView(view);
}
}
}
However this did not work because
하지만 이것은 작동하지 않았습니다.
heightSize = View.MeasureSpec.getSize(heightSpec);
returns a very large value that appear to be related to match_parent
.
해당 함수는 match\_parent와 관련된 매우 큰 값을 반환합니다.
By commenting height = heightSize;
(in the second switch case) I managed to make the height work but only if a TextView
child inside the CardView
does not wrap its own text (a long sentence).
CardView 내부에 있는 TextView가 텍스트를 감싸지 않은 경우(긴 문장이 없는 경우), heightSize를 그대로 적용하여 높이를 설정할 수 있었습니다. 두 번째 switch 케이스에서 height = heightSize; 주석 처리를 함으로써 높이를 적용할 수 있었습니다.
As soon as that TextView
wraps it's own text the height SHOULD increase but it doesn't. It calculated the height for that long sentence as a single line, not a wrapped line (2 or more).
해당 TextView의 텍스트가 한 줄이 아니라 여러 줄이 될 경우, 높이가 늘어나야 하지만 그렇지 않습니다. 긴 문장에 대해 높이를 계산할 때 해당 텍스트뷰의 높이를 한 줄로 계산하고 있기 때문입니다.
Any advice on how I should improve this LayoutManager
so my RecyclerView
works with WRAP_CONTENT
?
어떻게하면 RecyclerView가 WRAP_CONTENT와 함께 작동하는 LayoutManager를 개선할 수 있는지에 대한 조언이 있나요?
Edit: This layout manager might work for most people, but it still has problems with scrolling and calculating heights of wrapping textviews
편집: 이 레이아웃 매니저는 대부분의 사람들에게 작동할 수 있지만, 스크롤링 및 텍스트 래핑의 높이 계산에 문제가 있을 수 있습니다.
public class MyLinearLayoutManager extends LinearLayoutManager {
public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
private int[] mMeasuredDimension = new int[2];
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
int width = 0;
int height = 0;
for (int i = 0; i < getItemCount(); i++) {
measureScrapChild(recycler, i,
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
if (getOrientation() == HORIZONTAL) {
width = width + mMeasuredDimension[0];
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
height = height + mMeasuredDimension[1];
if (i == 0) {
width = mMeasuredDimension[0];
}
}
}
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
width = widthSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
height = heightSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
setMeasuredDimension(width, height);
}
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
View view = recycler.getViewForPosition(position);
if (view != null) {
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
getPaddingLeft() + getPaddingRight(), p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
getPaddingTop() + getPaddingBottom(), p.height);
view.measure(childWidthSpec, childHeightSpec);
measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
recycler.recycleView(view);
}
}
}
높은 점수를 받은 Solution
From Android Support Library 23.2.1 update, all WRAP_CONTENT should work correctly.
안드로이드 서포트 라이브러리 23.2.1 업데이트부터는 모든 WRAP_CONTENT가 올바르게 작동해야 합니다.
Please update version of a library in gradle
file OR to further :
gradle 파일에서 라이브러리 버전을 업데이트하거나, 더 나은 방법으로:
compile 'com.android.support:recyclerview-v7:23.2.1'
solved some issue like Fixed bugs related to various measure-spec methods
해결된 문제들 중 일부는 측정 지정(spec) 방법과 관련된 버그를 수정했습니다.
Check http://developer.android.com/tools/support-library/features.html#v7-recyclerview
(http://developer.android.com/tools/support-library/features.html#v7-recyclerview%EB%A5%BC) 확인하세요.
you can check Support Library revision history
Support Library의 변경 내역을 확인할 수 있습니다.
가장 최근 달린 Solution
Simply put your RecyclerView inside a NestedScrollView. Works perfectly
간단히 말해서 RecyclerView를 NestedScrollView 안에 넣으면 완벽하게 작동합니다.
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="25dp">
<android.support.v7.widget.RecyclerView
android:id="@+id/kliste"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>
출처 : https://stackoverflow.com/questions/27475178/how-do-i-make-wrap-content-work-on-a-recyclerview
'개발 > 안드로이드' 카테고리의 다른 글
Gradle에서 transitive = true의 동작 방식 (0) | 2023.01.24 |
---|---|
텍스트뷰 왼쪽 드로어블을 프로그래밍 방식으로 설정하기 (0) | 2023.01.23 |
LinearLayout에서 차일드 뷰들 사이에 프로그래밍 방식으로 패딩 주기 (0) | 2023.01.22 |
APK 파일에서 AndroidManifest.xml을 보기 (0) | 2023.01.20 |
안드로이드에서 "뒤로" 버튼을 눌러도 Activity가 종료되지 않게 하는 방법 (0) | 2023.01.20 |