동적이지만 정사각형 레이아웃을 수행하는 간단한 방법
나는 GridView
본질적으로 많은 뷰를 표시하기 위해 를 사용하고 있습니다 LinearLayouts
. 나는 LinearLayouts
모두 정사각형이 되길 원하지만 동적 크기를 원합니다. 즉, 두 개의 열 LinearLayouts
이 있고 화면 크기에 따라 늘어나지 만 정사각형으로 유지 되기를 원합니다 . xml
레이아웃을 통해이 작업을 수행하는 방법이 있습니까? 아니면 프로그래밍 방식으로 높이와 너비를 설정해야합니까?
정사각형 GridView
항목에 대한 깔끔한 솔루션은 다음 과 같이 확장 RelativeLayout
하거나 LinearLayout
재정의하는 onMeasure
것입니다.
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
답변이 늦어 질 수 있지만 그래도 새로운 방문객에게 도움이 될 것입니다.
Android Studio 2.3에 도입 된 새로운 ConstraintLayout 으로 이제 반응 형 레이아웃을 구축하는 것이 매우 쉽습니다.
부모 ConstraintLayout에서 자식 뷰 / 레이아웃을 동적으로 정사각형으로 만들려면이 속성을 추가합니다.
app:layout_constraintDimensionRatio="w,1:1"
w는 너비 방향 제약을 지정하는 것이고 1 : 1 비율은 정사각형 레이아웃을 보장합니다.
xml에는 width 및 height 속성을 연결할 수있는 것이 없습니다. 아마도 가장 쉬운 방법은 하위 클래스를 LinearLayout
만들고 재정의하는 것입니다.onMeasure
@Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int size = width > height ? height : width;
setMeasuredDimension(size, size);
}
나는 이것을 사용하여 항상 이전에 정사각형 인 뷰를 만들었습니다. 여전히 LinearLayout
.
이 작업에 도움이되는 추가 정보 : http://developer.android.com/guide/topics/ui/custom-components.html http://developer.android.com/reference/android/view/View.MeasureSpec.html
나는 이렇게했다 :
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int size;
if(widthMode == MeasureSpec.EXACTLY && widthSize > 0){
size = widthSize;
}
else if(heightMode == MeasureSpec.EXACTLY && heightSize > 0){
size = heightSize;
}
else{
size = widthSize < heightSize ? widthSize : heightSize;
}
int finalMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
super.onMeasure(finalMeasureSpec, finalMeasureSpec);
}
이 구현에서는 너비와 높이 사이의 크기가 더 낮다고 가정하여 레이아웃이 정사각형이됩니다. 또한 LinearLayout 내부에서 가중치를 사용하는 것과 같이 동적 값으로 설정할 수도 있습니다.
아주 간단한 방법으로 할 수 있습니다 super.onMeasure()
. 두 번만 전화하면 됩니다.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
int squareLen = Math.min(width, height);
super.onMeasure(
MeasureSpec.makeMeasureSpec(squareLen, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(squareLen, MeasureSpec.EXACTLY));
}
super.onMeasure()
두 번 호출 하면 그리기 프로세스 측면에서 덜 효율적이지만 다른 답변으로 인해 발생할 수있는 레이아웃 문제를 해결하는 간단한 방법입니다.
다음과 같이 간단합니다.
public class SquareRelativeLayout extends RelativeLayout {
public SquareRelativeLayout(Context context) {
super(context);
}
public SquareRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
if (widthMeasureSpec < heightMeasureSpec)
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
else
super.onMeasure(heightMeasureSpec, heightMeasureSpec);
}
}
다음은 view 또는 viewgroup으로 설정할 수있는 모든 레이아웃 매개 변수에 대해 작동하는 솔루션입니다.
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int widthDesc = MeasureSpec.getMode(widthMeasureSpec);
int heightDesc = MeasureSpec.getMode(heightMeasureSpec);
int size = 0;
if (widthDesc == MeasureSpec.UNSPECIFIED
&& heightDesc == MeasureSpec.UNSPECIFIED) {
size = DP(defaultSize); // Use your own default size, in our case
// it's 125dp
} else if ((widthDesc == MeasureSpec.UNSPECIFIED || heightDesc == MeasureSpec.UNSPECIFIED)
&& !(widthDesc == MeasureSpec.UNSPECIFIED && heightDesc == MeasureSpec.UNSPECIFIED)) {
//Only one of the dimensions has been specified so we choose the dimension that has a value (in the case of unspecified, the value assigned is 0)
size = width > height ? width : height;
} else {
//In all other cases both dimensions have been specified so we choose the smaller of the two
size = width > height ? height : width;
}
setMeasuredDimension(size, size);
건배
내 제안은 FrameLayout에서 상속하는 사용자 정의 레이아웃 클래스를 만드는 것입니다. OnMeasure () 메서드를 재정의하고 SquareFrameLayout 안에 사각형이 될 컨트롤을 넣으십시오.
이것이 Xamarin.Android에서 수행되는 방법입니다.
public class SquareFrameLayout : FrameLayout
{
private const string _tag = "SquareFrameLayout";
public SquareFrameLayout(Android.Content.Context context):base(context) {}
public SquareFrameLayout(IntPtr javaReference, Android.Runtime.JniHandleOwnership transfer):base(javaReference, transfer) {}
public SquareFrameLayout(Android.Content.Context context, IAttributeSet attrs):base(context, attrs) {}
public SquareFrameLayout(Android.Content.Context context, IAttributeSet attrs, int defStyleAttr):base(context, attrs, defStyleAttr) {}
public SquareFrameLayout(Android.Content.Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes):base(context, attrs, defStyleAttr, defStyleRes) {}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
var widthMode = MeasureSpec.GetMode(widthMeasureSpec);
int widthSize = MeasureSpec.GetSize(widthMeasureSpec);
var heightMode = MeasureSpec.GetMode(heightMeasureSpec);
int heightSize = MeasureSpec.GetSize(heightMeasureSpec);
int width, height;
switch (widthMode)
{
case MeasureSpecMode.Exactly:
width = widthSize;
break;
case MeasureSpecMode.AtMost:
width = Math.Min(widthSize, heightSize);
break;
default:
width = 100;
break;
}
switch (heightMode)
{
case MeasureSpecMode.Exactly:
height = heightSize;
break;
case MeasureSpecMode.AtMost:
height = Math.Min(widthSize, heightSize);
break;
default:
height = 100;
break;
}
Log.Debug(_tag, $"OnMeasure({widthMeasureSpec}, {heightMeasureSpec}) => Width mode: {widthMode}, Width: {widthSize}/{width}, Height mode: {heightMode}, Height: {heightSize}/{height}");
var size = Math.Min(width, height);
var newMeasureSpec = MeasureSpec.MakeMeasureSpec(size, MeasureSpecMode.Exactly);
base.OnMeasure(newMeasureSpec, newMeasureSpec);
}
}
If you want a View (or any other control) to be square (and centered) just add it to your layout the following way:
<your.namespace.SquareFrameLayout
android:id="@+id/squareContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<View
android:id="@+id/squareContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</your.namespace.SquareFrameLayout>
Check out SquareLayout, an Android Library which provides a wrapper class for different Layouts, rendering them Squared dimensioned without losing any core functionalities.
The dimensions are calculated just before the Layout is rendered, hence there is no re-rendering or anything as such to adjust once the View is obtained.
To use the Library, add this to your build.gradle:
repositories {
maven {
url "https://maven.google.com"
}
}
dependencies {
compile 'com.github.kaushikthedeveloper:squarelayout:0.0.3'
}
The one you require is SquareLinearLayout.
For anyone wants solution With Kotlin, here's what I did with FrameLayout
.
package your.package.name
import android.content.Context
import android.util.AttributeSet
import android.widget.FrameLayout
class SquareLayout: FrameLayout {
constructor(ctx: Context) : super(ctx)
constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
if (widthMeasureSpec < heightMeasureSpec)
super.onMeasure(widthMeasureSpec, widthMeasureSpec)
else
super.onMeasure(heightMeasureSpec, heightMeasureSpec)
}
}
참고URL : https://stackoverflow.com/questions/8981029/simple-way-to-do-dynamic-but-square-layout
'development' 카테고리의 다른 글
ActionBar 안에 아이콘과 작업 제목을 모두 표시하는 방법은 무엇입니까? (0) | 2020.10.16 |
---|---|
한 줄에 하나의 항목이있는 두 텍스트 파일의 차이점 찾기 (0) | 2020.10.15 |
UILabel의 textColor 속성에 애니메이션을 적용하는 방법은 무엇입니까? (0) | 2020.10.15 |
지연된 함수 호출 (0) | 2020.10.15 |
Scala에서 List에서 고유 한 항목을 찾는 방법 (0) | 2020.10.15 |