গতিশীল তবে বর্গক্ষেত্র বিন্যাস করার সহজ উপায়


84

আমি GridViewএকটি গোছা ভিউগুলি প্রদর্শনের জন্য ব্যবহার করছি যা মূলত LinearLayouts। আমি LinearLayoutsসমস্তটি বর্গক্ষেত্র হতে চাই , তবে আমি এগুলিটিও গতিশীল আকারের করতে চাই - অর্থাৎ দুটি কলাম রয়েছে এবং আমি LinearLayoutsপর্দার আকারের উপর নির্ভর করে প্রসারিত করতে চাই তবে বর্গক্ষেত্র বজায় রাখতে চাই। xmlবিন্যাসের মাধ্যমে এটি করার কোনও উপায় আছে বা আমাকে প্রোগ্রামিকভাবে উচ্চতা এবং প্রস্থগুলি সেট করতে হবে?

উত্তর:


113

বর্গক্ষেত্রের GridViewআইটেমগুলির জন্য একটি ঝরঝরে সমাধান হ'ল প্রসারিত RelativeLayoutবা এর মতো LinearLayoutওভাররাইড করা onMeasure:

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}

4
এটি setMeasuredDimesion () ব্যবহার না করে পরিমাপের বৈশিষ্টটি ব্যবহার করছে যাতে এটি ভাল। যদিও এটি সর্বদা প্রস্থ নেয় তখন এটি খুব নমনীয় নয়।
আদম

4
@ ডেভিড মেরিম্যান যেমনটি উপরে বলেছিলেন, ভিউটি যদি এটির চেয়ে লম্বা হয় তার চেয়ে প্রশস্ত হয়, এর ফলে দৃশ্যের অংশটি কেটে দেখার ক্ষেত্রের নীচে প্রসারিত হবে।
vcapra1

4
এটি যদি ম্যাথ.মিনের (প্রস্থমাজারস্পেক, উচ্চতামর্যাদার স্পেস) মানকে সুপার.অনমেজার () এর উভয় আর্গুমেন্টে পাস করে তবে এটি আরও নমনীয় হবে
পল উইন্টজ

এটি ক্রিয়াকলাপগুলির সাথে সহজেই কাজ করবে তবে এটি কোনও অ্যাপ্লিকেশন উইজেটের সাথে কাজ করবে না।
অ্যাপোলো-রোবটো

73

উত্তর দিতে দেরি হতে পারে তবে তবুও এটি নতুন দর্শকদের পক্ষে সহায়ক হবে।

অ্যান্ড্রয়েড স্টুডিও ২.৩ এ নতুন কনস্ট্রেন্টলয়েট চালু হওয়ার সাথে সাথে এখন প্রতিক্রিয়াশীল লেআউটগুলি তৈরি করা বেশ সহজ।

কোনও প্যারেন্ট কনস্ট্রেন্টলয়েট-এ, তার শিশুদের যে কোনও একটিকে গতিবদ্ধভাবে চৌম্বক দেখা / বিন্যাস করতে, এই বৈশিষ্ট্যটি যুক্ত করুন

app:layout_constraintDimensionRatio="w,1:1"

ডাব্লু প্রস্থ অনুসারে সীমাবদ্ধতা নির্দিষ্ট করতে হবে এবং 1: 1 অনুপাত বর্গ বিন্যাস নিশ্চিত করে।


9
এটি রাজার উত্তর
Itzhar

4
শীর্ষস্থানীয় উত্তর যদি আপনি বর্গ হিসাবে কোনও বিদ্যমান লেআউট প্রদর্শন করতে চান!
কোয়ান্টিন ক্লিন

9
শিশু বিন্যাসে লেআউটের প্রস্থ এবং উচ্চতার জন্য "0 ডিপি" সেট করা নিশ্চিত করুন। অন্যথায় এটি কাজ করবে না।
থিলিনা কেজে

এটি নিজেই এই দর্শনটির জন্য কাজ করে, আমি বলতে চাইছি যদি আপনি কোনও কনট্রেন্টলআউট এর সন্তানের বর্গক্ষেত্র হতে চান তবে আপনি সরাসরি শিশু দৃশ্যে বিন্যাস_সংশ্লিষ্টতার মাত্রা অনুপাতটি সংজ্ঞায়িত করতে পারেন
Plinio.Santos

4
সমাধানের জন্য আপনাকে অনেক ধন্যবাদ; যদি এটি আপনার সলিউশন ব্যবহার আমার কোড একটি সম্পূর্ণ সারকথা সাহায্য করে আমি তৈরি করেছি gist.github.com/nadar71/006699e31ef7451813e6c97dacfbc5e2
android_dev71

44

এক্সএমএলে এমন কিছুই নেই যা আপনাকে প্রস্থ এবং উচ্চতার বৈশিষ্ট্যগুলিকে লিঙ্ক করতে দেয়। সম্ভবত সবচেয়ে সহজ কাজটি হচ্ছে সাবক্লাস 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/references/android/view/View.MeasureSpec.html


হ্যাঁ, আমি একই জাতীয় কিছু শেষ করেছি। ধন্যবাদ!
ক্যাথরিন

4
এটি যদি আপনার পক্ষে কাজ করে তবে আপনি কি এটি সঠিক উত্তর হিসাবে চিহ্নিত করতে পারেন?
ডেভিড মেরিম্যান 24'12

4
@ ক্যাথরিন হে ক্যাথরিন, আপনি কি আপনার স্নিপেট পোস্ট করতে পারবেন? হতে পারে এটি অন্যের জন্য উপকারী হবে :-)
মেরেক সেবেরা

4
যোগ করতে ভুলে গেছি না: super.onMeasure(widthMeasureSpec, widthMeasureSpec);!
deKajoo

4
@ ডি কেজু ইউজিং super.onMeasure(widthMeasureSpec, widthMeasureSpec);আপনাকে স্কোয়ার দেয় তবে এটি সর্বদা এক্স প্রস্থ। প্রদত্ত পরিমাপগুলি যদি সেগুলির চেয়ে লম্বা হয় তবে আপনার সমস্যা হতে চলেছে। আমার দ্রবণটি দুটি পরিমাপের থেকে ছোটটি ব্যবহার করে, যাতে আপনি সর্বদা বৃহত্তম বর্গক্ষেত্র পান যা প্রদত্ত আয়তক্ষেত্রের মধ্যে উপযুক্ত হবে।
ডেভিড মেরিম্যান

43

আমি এইভাবে করেছি:

@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);
}

এই বাস্তবায়নের সাথে সাথে, আপনার বিন্যাসটি বর্গক্ষেত্র হবে, প্রস্থ এবং উচ্চতার মধ্যে নিম্ন আকার ধরে। এমনকি এটি গতিশীল মানগুলির সাথেও সেট করা যেতে পারে যেমন লিনিয়ারলআউটের অভ্যন্তরে ওজন ব্যবহার করা।


"onMeasure" পদ্ধতিটি এমন কোনও শ্রেণিতে ওভাররাইড করা উচিত যা গ্রিডভিউ প্রসারিত করে?
অ্যানড্রয়েড

ক্লাসে টিটির ওভাররাইডেন আপনি চান এটি বর্গক্ষেত্র হোক। প্রশ্নের ক্ষেত্রে, এটি গ্রিডভিউয়ের ভিতরে লিনিয়ারলআউটগুলি।
ফার্নান্দো কামারগো

এই একটি আমাকে স্ট্যাজার্ডগ্রিডগ্রিডলআউটে স্কোয়ার ভিউ ব্যবহার করে কিছু অদ্ভুত সমস্যা সমাধান করতে সহায়তা করেছিল। আমার আরও নিষ্পাপ বাস্তবায়ন যথেষ্ট ভাল ছিল না। ধন্যবাদ!
পিটারডক

10

আমরা এটি খুব সহজ উপায়ে করতে পারি - কেবল 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()দু'বার ফোন করে, অঙ্কন প্রক্রিয়ার ক্ষেত্রে এটি কম দক্ষ তবে অন্য উত্তরগুলির কারণ হতে পারে এমন লেআউট সংক্রান্ত সমস্যাগুলি ঠিক করার এটি একটি সহজ উপায়।


4
সুপার.অনমাজারকে দু'বার কল করার পরিবর্তে, দ্বিতীয় বার আপনাকে কেবল সেটমিজুরডিমাইশন (স্কোয়ারলেন, স্কোয়ারলেন) কল করতে হবে;
ব্যবহারকারী3802077

super.onMeasure()দু'বার কল করা নিশ্চিত করে যে লেআউটটি সঠিকভাবে ভিউর নতুন আকারের দ্বারা সম্পন্ন হয়েছে। এটি ছাড়া আমাদের একটি ভিন্ন উপায়ে একটি বিন্যাস ট্রিগার করতে হবে বা ভুল লেআউটগুলি মোকাবেলা করতে হবে।
রিচার্ড লে ম্যাসুরিয়ার

4

এটি যেমন সহজ:

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);
    }
}

2

এক্সএমএলে নিম্নলিখিত লাইনটি যুক্ত করুন:

app:layout_constraintDimensionRatio="1:1"

4
আমি একই উত্তরটি পোস্ট করতে চেয়েছিলাম কারণ এটি অ্যাপ্লিকেশনের চেয়ে ভাল: লেআউট_কন্ট্রেন্টডাইমেনশন রেটিও = "ডাব্লু, 1: 1" যেমন আপনি সর্বদা অনুপাত বজায় রাখেন যদি আপনি কনফিগারেশন পরিবর্তন করেন
আলেক্সি সিমচেনকো

1

এখানে এমন একটি সমাধান রয়েছে যা সমস্ত লেআউট প্যারামিটারগুলির জন্য কাজ করে যা দেখার বা ভিউগ্রুপ সেট করা যেতে পারে:

    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);

চিয়ার্স


এই উত্তরের কিছু আকর্ষণীয় বৈশিষ্ট্য রয়েছে এবং এটি সম্ভবত আরও দৃust়, তবে কাজের প্রয়োজন এবং মাপের চশমাগুলি তৈরি করা উচিত যা সেট মাইজারডাইমেনশন () এর পরিবর্তে সুপার.অনম্যাসার () কে পাস হয় কারণ এটি বিভিন্ন সুপার ক্লাসের অনুমতি দেয়।
আদম

1

আমার পরামর্শ হ'ল ফ্রেমলাউট থেকে উত্তরাধিকার সূত্রে একটি কাস্টম লেআউট ক্লাস তৈরি করা। OnMeasure () পদ্ধতিটি ওভাররাইড করুন এবং আপনি যে স্কয়ারফ্রেমলাউটটির অভ্যন্তরে বর্গক্ষেত্র হতে চান তা নিয়ন্ত্রণ করুন।

এটি এটি 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);
    }
}

আপনি যদি কোনও ভিউ (বা অন্য কোনও নিয়ন্ত্রণ) বর্গক্ষেত্র হতে চান (এবং কেন্দ্রিক) কেবলমাত্র আপনার লেআউটে নিম্নলিখিত উপায়ে যুক্ত করুন:

<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>

0

স্কয়ারএলআউট , একটি অ্যান্ড্রয়েড লাইব্রেরি যা বিভিন্ন লেআউটগুলির জন্য একটি র‌্যাপার ক্লাস সরবরাহ করে, কোনও মূল কার্যকারিতা হারিয়ে না দিয়ে স্কোয়ারের মাত্রিক আকার দেয় Check

মাত্রা গণনা করা হয় ঠিক আগে লেআউট পেশ করা হয়েছে , অত কোন পুনরায় রেন্ডারিং বা যেমন কিছু একবার দেখুন প্রাপ্ত হয় সমন্বয় হয়।

লাইব্রেরিটি ব্যবহার করতে, আপনার বিল্ডড্র্যাডলে এটি যুক্ত করুন:

repositories {
    maven {
        url "https://maven.google.com"
    }
}

dependencies {
    compile 'com.github.kaushikthedeveloper:squarelayout:0.0.3'
}

আপনার যা প্রয়োজন তা হ'ল স্কয়ারলাইনারলআউট


সত্যিকারের ডিভাইসে আমার পক্ষে কাজ করে না :( অ্যান্ড্রয়েড স্টুডিওর পূর্বরূপে ভাল রেন্ডারিং, তবে ডিভাইসে কাজ করছে না
ইউজিন ভোরোনয়

0

যে কেউ কোটলিনের সাথে সমাধান চায়, আমি যা করেছি তা এখানে 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)
    }
}

0

এই কোড ব্যবহার করে দেখুন:

public class SquareRelativeLayout extends RelativeLayout {
    public SquareRelativeLayout(Context context) {
        super(context);
    }

    public SquareRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @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);
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.