আমি কীভাবে অ্যান্ড্রয়েডে ফ্লোলআউট জাতীয় কিছু করতে পারি?


উত্তর:


91

আপনি কথা বলতে আমি Devoxx বিশ্ববিদ্যালয়ের দিনে দিয়েছেন (উপলব্ধ ঘড়ি যদি parleys.com ) আপনি এটি নিজে করবেন কিভাবে শিখতে হবে। আলাপ চলাকালীন আমি FlowLayoutকাস্টম লেআউট লিখতে কতটা সহজ তা দেখানোর জন্য মঞ্চে একটি বাস্তবায়ন লাইভ লিখেছিলাম ।

বাস্তবায়ন এখানে হোস্ট করা হয়


18
ধন্যবাদ রোমেন লোক, এটি সত্যিই সাহায্য করে। কীভাবে সমাধান দেবেন? বা লিঙ্ক? ... আপনি কীভাবে উত্তরটি গ্রহণ করেছিলেন তা আমি পাই না।
জোহান হিলবোল্ড

4
@ জোহানহিলবোল্ড: আমি কেবল লিঙ্কগুলি যুক্ত করেছি
ম্যাকার্সে

7
পাঠকরা সচেতন হন যে লিঙ্কটির কোডটিতে কিছু গুরুতর সমস্যা রয়েছে এবং এটি ড্রপ-ইন সমাধান থেকে অনেক দূরে। এই ছোট কোড বেসটিতে ইতিমধ্যে আমার দুটি বড় সমস্যা ছিল। আমি ফিক্সগুলি পোস্ট করব না কারণ তারা আমার বিশেষ প্রয়োজনের জন্য নালী টেপ সমাধান ...
নেমানজা কোভাসেভিচ

6
আমি কখনই দাবি করিনি এটি নিখুঁত ছিল :)
রোমেন গাই

19
@ রোমেনগুয়ির মুল বক্তব্যটি হ'ল, সম্ভবত এতটা সহজ কিছু পরে না।
জেফ্রি ব্লাটম্যান

75

আপনার গুণাবলীর FlexboxLayoutসাথে ব্যবহার করা উচিত flexWrap="wrap"

<com.google.android.flexbox.FlexboxLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     app:flexWrap="wrap">

<!-- contents go here -->

</com.google.android.flexbox.FlexboxLayout>

বিল্ড নির্দেশাবলীর জন্য, গিথুব রেপো দেখুন।

ফ্লেক্সবক্সলআউট এর ভিজ্যুয়াল উপস্থাপনা এ সম্পর্কে আরও - https://android-developers.googleblog.com/2017/02/build-flexible-layouts-with.html


8
এটি সর্বশেষতম এবং এখন পর্যন্ত সেরা সমাধান।
তৌহিদ

4
এটি সমাধান হিসাবে চিহ্নিত করা উচিত! এখন পর্যন্ত এই সমস্যার সর্বোত্তম উত্তর
x10sion

4
এই উত্তরে যোগ করতে, যদি আপনি কোনও পুনর্ব্যবহারযোগ্য ভিউতে এই প্রভাবটি রাখতে চান তবে এই লাইবটির একটি লেআউট ম্যানেজারও রয়েছে
এরি

4
বিঙ্গো, বাংগো, বনগো অ্যান্ড্রয়েডে ফ্লেক্সবক্স ব্যবহারের জন্য আশ্চর্য গ্রন্থাগার। সুন্দর.
জোশুয়া পিন্টার

23

রোমেন গায়ের উত্তরে মন্তব্য পোস্ট করার মতো যথেষ্ট খ্যাতি আমার নেই তবে এই উত্তরটি এখানেই হওয়া উচিত (আমি কেবল আমার সম্পাদনাটি ভাগ করে নেওয়ার জন্য একটি অ্যাকাউন্ট তৈরি করেছি)।

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

নিম্নলিখিত পরিবর্তন "নতুন লাইনে থাকলে শেষ সন্তানের ক্লিপ করা হয়" এর সমস্যার সমাধান করে:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    int widthLimit = MeasureSpec.getSize(widthMeasureSpec) - getPaddingRight();
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);

    boolean growHeight = widthMode != MeasureSpec.UNSPECIFIED;

    int width = 0;

    int currentWidth = getPaddingLeft();
    int currentHeight = getPaddingTop();

    int maxChildHeight = 0;

    boolean breakLine = false;
    boolean newLine = false;
    int spacing = 0;

    final int count = getChildCount();
    for (int i = 0; i < count; i++)
    {
        View child = getChildAt(i);
        measureChild(child, widthMeasureSpec, heightMeasureSpec);

        LayoutParams lp = (LayoutParams) child.getLayoutParams();
        spacing = mHorizontalSpacing;

        if (lp.horizontalSpacing >= 0)
        {
            spacing = lp.horizontalSpacing;
        }

        if (growHeight && (breakLine || ((currentWidth + child.getMeasuredWidth()) > widthLimit)))
        {               
            newLine = true;
            currentHeight += maxChildHeight + mVerticalSpacing;

            width = Math.max(width, currentWidth - spacing);

            currentWidth = getPaddingLeft();
            maxChildHeight = 0;
        }
        else
        {
            newLine = false;
        }

        maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());

        lp.x = currentWidth;
        lp.y = currentHeight;

        currentWidth += child.getMeasuredWidth() + spacing;

        breakLine = lp.breakLine;
    }

    if (newLine == false)
    {
        width = Math.max(width, currentWidth - spacing);
    }

    width += getPaddingRight();
    int height = currentHeight + maxChildHeight + getPaddingBottom();

    setMeasuredDimension(resolveSize(width, widthMeasureSpec),
            resolveSize(height, heightMeasureSpec));
}

9

গুগল থেকে একটি লাইব্রেরি রয়েছে, যার নাম "ফ্লেক্সবক্স-লেআউট" । আপনি এটি পরীক্ষা করা উচিত।

এটি রিসাইক্লারভিউতে ব্যবহার করতে, আপনি এর মতো কিছু ব্যবহার করতে পারেন:

val layoutManager = FlexboxLayoutManager(activity)
layoutManager.flexDirection = FlexDirection.ROW
layoutManager.flexWrap = FlexWrap.WRAP
layoutManager.justifyContent = JustifyContent.FLEX_START
layoutManager.alignItems = AlignItems.FLEX_START 
recyclerView.layoutManager=layoutManager

6

পূর্ববর্তী উত্তরগুলির মতো, আমি সমাধানটি এখানেই শুরু করেছি: http://hzqtc.github.io/2013/12/android-custom-layout-flowlayout.html

আমি নীচে শিশুদের বিভিন্ন উচ্চতা জন্য অ্যাকাউন্টে এটি প্রসারিত।

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

// Custom layout that wraps child views to a new line
public class FlowLayout extends ViewGroup {

    private int marginHorizontal;
    private int marginVertical;

    public FlowLayout(Context context) {
        super(context);
        init();
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() { // Specify the margins for the children
        marginHorizontal = getResources().getDimensionPixelSize(R.dimen.activity_half_horizontal_margin);
        marginVertical = getResources().getDimensionPixelSize(R.dimen.activity_half_vertical_margin);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();
        int lowestBottom = 0;
        int lineHeight = 0;
        int myWidth = resolveSize(100, widthMeasureSpec);
        int wantedHeight = 0;

        for (int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) {
                continue;
            }

            child.measure(getChildMeasureSpec(widthMeasureSpec, 0, child.getLayoutParams().width),
                    getChildMeasureSpec(heightMeasureSpec, 0, child.getLayoutParams().height));
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            lineHeight = Math.max(childHeight, lineHeight);

            if (childWidth + childLeft + getPaddingRight() > myWidth) { // Wrap this line
                childLeft = getPaddingLeft();
                childTop = marginVertical + lowestBottom; // Spaced below the previous lowest point
                lineHeight = childHeight;
            }
            childLeft += childWidth + marginHorizontal;

            if (childHeight + childTop > lowestBottom) { // New lowest point
                lowestBottom = childHeight + childTop;
            }
        }

        wantedHeight += childTop + lineHeight + getPaddingBottom();
        setMeasuredDimension(myWidth, resolveSize(wantedHeight, heightMeasureSpec));
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();
        int lowestBottom = 0;
        int myWidth = right - left;
        for (int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) {
                continue;
            }
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            if (childWidth + childLeft + getPaddingRight() > myWidth) { // Wrap this line
                childLeft = getPaddingLeft();
                childTop = marginVertical + lowestBottom; // Spaced below the previous lowest point
            }
            child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
            childLeft += childWidth + marginHorizontal;

            if (childHeight + childTop > lowestBottom) { // New lowest point
                lowestBottom = childHeight + childTop;
            }
        }
    }
}

মাল্টি-লাইন টেক্সটএডিটস মোড়ানোর জন্য সমাধান হিসাবে আমি এটি ব্যবহার করেছি। আশা করি এটা সাহায্য করবে!


কিছু ক্ষেত্রে খুব দরকারী। এখানে একটি সংশোধনী যা মার্জিনআলআউটপ্যারামগুলিকে সমর্থন করে।
jk7

চমৎকার সমাধান! মার্জিনটি কেবল এন্টার পদ্ধতিতে সেট করার পরে কাজ করছে তবে বিন্যাস থেকে নয়।
প্রতীক সালুজা

6

এখানে কাস্টম ক্লাসটি রয়েছে যেখানে আপনি ডায়নামিক্যালি ভিউ যুক্ত করে (যেমন ফ্লোলেআউটও বলা হয়) যুক্ত করে লেআউটটি অর্জন করতে পারেন।

এখানে চিত্র বর্ণনা লিখুন

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/*
Created By Dhavalkumar Solanki
* */
public class FlowLayout extends ViewGroup {

    private int line_height_space;

    public static class LayoutParams extends ViewGroup.LayoutParams {

        public int horizontal_spacing;
        public int vertical_spacing;

        /**
         * @param horizontal_spacing Pixels between items, horizontally
         * @param vertical_spacing   Pixels between items, vertically
         */
        public LayoutParams(int horizontal_spacing, int vertical_spacing) {
            super(0, 0);
            this.horizontal_spacing = horizontal_spacing;
            this.vertical_spacing = vertical_spacing;
        }
    }

    public FlowLayout(Context context) {
        super(context);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        assert (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED);

        final int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
        int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
        final int count = getChildCount();
        int line_height_space = 0;

        int xpos = getPaddingLeft();
        int ypos = getPaddingTop();

        int childHeightMeasureSpec;
        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
        } else {
            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }


        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), childHeightMeasureSpec);
                final int childw = child.getMeasuredWidth();
                line_height_space = Math.max(line_height_space, child.getMeasuredHeight() + lp.vertical_spacing);

                if (xpos + childw > width) {
                    xpos = getPaddingLeft();
                    ypos += line_height_space;
                }

                xpos += childw + lp.horizontal_spacing;
            }
        }
        this.line_height_space = line_height_space;

        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) {
            height = ypos + line_height_space;

        } else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
            if (ypos + line_height_space < height) {
                height = ypos + line_height_space;
            }
        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(1, 1); // default of 1px spacing
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        if (p instanceof LayoutParams) {
            return true;
        }
        return false;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        final int count = getChildCount();
        final int width = r - l;
        int xpos = getPaddingLeft();
        int ypos = getPaddingTop();

        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                final int childw = child.getMeasuredWidth();
                final int childh = child.getMeasuredHeight();
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                if (xpos + childw > width) {
                    xpos = getPaddingLeft();
                    ypos += line_height_space;
                }
                child.layout(xpos, ypos, xpos + childw, ypos + childh);
                xpos += childw + lp.horizontal_spacing;
            }
        }
    }
}

উদাহরণ:

পাঠ্য_দর্শন.এক্সএমএল

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tool="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="5dp">

    <TextView
        android:id="@+id/tvText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="19sp"
        android:background="@drawable/unselected_tag"
        android:textColor="@color/colorPrimary"
        tool:text="Temp" />
</RelativeLayout>

ক্রিয়াকলাপ_প্রবাহ_ালয়__ডেমো.এক্সএমএল

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    >
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tvTitleBusiness"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Business Interest "
                    android:textColor="@color/colorPrimary"
                    android:textSize="25sp" />

                <com.example.tristateandroid2.radardemo.FlowLayout
                    android:id="@+id/flowBusiness"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                </com.example.tristateandroid2.radardemo.FlowLayout>
            </LinearLayout>

            <LinearLayout
                android:layout_marginTop="@dimen/activity_horizontal_margin"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tvTitlePrivate"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Private Interest "
                    android:textColor="@color/colorPrimary"
                    android:textSize="25sp" />

                <com.example.tristateandroid2.radardemo.FlowLayout
                    android:id="@+id/flowPrivate"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                </com.example.tristateandroid2.radardemo.FlowLayout>
            </LinearLayout>
        </LinearLayout>
    </ScrollView>
</RelativeLayout>

ফ্লোলাউডেমো.জভা

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;

public class FlowLayouDemo extends AppCompatActivity {
    private TextView tvTitleBusiness;
    private FlowLayout flowBusiness;
    private TextView tvTitlePrivate;
    private FlowLayout flowPrivate;
    private ArrayList<TagModel> arrayList;

    private void findViews() {
        tvTitleBusiness = (TextView) findViewById(R.id.tvTitleBusiness);
        flowBusiness = (FlowLayout) findViewById(R.id.flowBusiness);
        tvTitlePrivate = (TextView) findViewById(R.id.tvTitlePrivate);
        flowPrivate = (FlowLayout) findViewById(R.id.flowPrivate);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flow_layou_demo);
        findViews();
        addLayouts();
    }

    private void addLayouts() {
        if (arrayList == null) {
            arrayList = new ArrayList<>();
        }
        flowBusiness.removeAllViews();
        flowPrivate.removeAllViews();
        for (int i = 0; i < 75; i++) {

            final boolean[] selected = {false};
            View view = this.getLayoutInflater().inflate(R.layout.text_view, null);
            final TextView textView = (TextView) view.findViewById(R.id.tvText);
            if (i % 5 == 0) {
                arrayList.add(new TagModel(i, false, "Business VIEW : " + i));
                textView.setText("Busi VIEW To  IS : " + i);
            } else {
                arrayList.add(new TagModel(i, false, "TEXT IS : " + i));
                textView.setText("Busi IS : " + i);
            }
            textView.setBackgroundResource(R.drawable.unselected_tag);
            textView.setTextColor(Color.parseColor("#3F51B5"));
            textView.setTag(i);
            if(i<=50){
                flowBusiness.addView(view);
            }else {
                textView.setText("Priv View : "+i);
                flowPrivate.addView(view);
            }

            textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (selected[0]) {
                        selected[0] = false;
                        textView.setBackgroundResource(R.drawable.unselected_tag);
                        textView.setTextColor(Color.parseColor("#3F51B5"));
                    } else {
                        selected[0] = true;
                        textView.setBackgroundResource(R.drawable.selected_tag);
                        textView.setTextColor(Color.parseColor("#FFFFFF"));
                    }
                }
            });

        }
    }
}

4
দুর্দান্ত ক্লাস, তবে ডান থেকে বাম লেআউট দিকটি সমর্থন করার জন্য এটি কিছু কাজ করতে হবে।
টেড হপ

কেন্দ্রে আইটেম তৈরি করতে।
অভিষেক সি

java.lang.ClassCastException: android.widget.LinearLayout $ LayoutParams com.nuveda.fillintheblank.FlowLayout $ লেআউটপ্যারামস
কুমার এম

আমি মনে করি আপনি আপনার লেআউটটির জন্য ডায়নামিক প্যারাম সেট করার চেষ্টা করছেন যাতে এটির সমস্যা তৈরি হয়, আমি রিলেটিভলআউট.লায়আউটপ্যারাম ব্যবহার করার পরামর্শ দিই।
ধাওয়াল সোলঙ্কি

3

@ ম্যাটনোটইকুয়ালস () ফ্লোএলআউটে একটি সংশোধন যা মার্জিনালাউটপ্যারামগুলিকে সমর্থন করে।

বাম, ডান, উপরের এবং নীচের মার্জিনগুলিকে সমর্থন করার জন্য এটি মার্জিনালাউটপর্মগুলির কেবলমাত্র একটি সংক্ষিপ্ত বাস্তবায়ন।

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/**
 *  Original version courtesy of MattNotEquals() at http://stackoverflow.com/a/34169798/4515489 - 4/13/17.
 *  7/15/17 Revised to support MarginLayoutParams.
 */
public class FlowLayout extends ViewGroup {
    // Custom layout that wraps child views to a new line.

    public FlowLayout(Context context) {
        super(context);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();
        int lowestBottom = 0;
        int lineHeight = 0;
        int myWidth = resolveSize(100, widthMeasureSpec);
        int wantedHeight = 0;
        for (int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) {
                continue;
            }
            child.measure(getChildMeasureSpec(widthMeasureSpec, 0, child.getLayoutParams().width),
                          getChildMeasureSpec(heightMeasureSpec, 0, child.getLayoutParams().height));
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            lineHeight = Math.max(childHeight, lineHeight);

            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            childLeft += lp.leftMargin;
            childTop += lp.topMargin;
            if (childLeft + childWidth + lp.rightMargin + getPaddingRight() > myWidth) { // Wrap this line
                childLeft = getPaddingLeft() + lp.leftMargin;
                childTop = lowestBottom + lp.topMargin; // Spaced below the previous lowest point
                lineHeight = childHeight;
            }
            childLeft += childWidth + lp.rightMargin;

            if (childTop + childHeight + lp.bottomMargin > lowestBottom) { // New lowest point
                lowestBottom = childTop + childHeight + lp.bottomMargin;
            }
        }
        wantedHeight += lowestBottom + getPaddingBottom(); // childTop + lineHeight + getPaddingBottom();
        setMeasuredDimension(myWidth, resolveSize(wantedHeight, heightMeasureSpec));
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();
        int lowestBottom = 0;
        int myWidth = right - left;
        for (int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) {
                continue;
            }
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            childLeft += lp.leftMargin;
            childTop += lp.topMargin;
            if (childLeft + childWidth + lp.rightMargin + getPaddingRight() > myWidth) { // Wrap this line
                childLeft = getPaddingLeft() + lp.leftMargin;
                childTop = lowestBottom + lp.topMargin; // Spaced below the previous lowest point
            }
            child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
            childLeft += childWidth + lp.rightMargin;

            if (childTop + childHeight + lp.bottomMargin > lowestBottom) { // New lowest point
                lowestBottom = childTop + childHeight + lp.bottomMargin;
            }
        }
    }

    @Override
    public boolean shouldDelayChildPressedState() {
        return false;
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof LayoutParams;
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new FlowLayout.LayoutParams(getContext(), attrs);
    }

    @Override
    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
        if (lp instanceof LayoutParams) {
            return new LayoutParams((LayoutParams) lp);
        }
        else if (lp instanceof MarginLayoutParams) {
            return new LayoutParams((MarginLayoutParams) lp);
        }
        else
            return super.generateLayoutParams(lp);
    }

    /**
     * Per-child layout information for layouts that support margins.
     */
    public static class LayoutParams extends MarginLayoutParams {
        public LayoutParams(@NonNull Context c, @Nullable AttributeSet attrs) {
            super(c, attrs);
        }
        public LayoutParams(int width, int height) {
            super(width, height);
        }
        public LayoutParams(@NonNull ViewGroup.LayoutParams source) {
            super(source);
        }
        public LayoutParams(@NonNull ViewGroup.MarginLayoutParams source) {
            super(source);
        }
        public LayoutParams(@NonNull LayoutParams source) {
            super(source);
        }
    }
}

আমি গত 2 ঘন্টা থেকে আমার মাথা স্ক্র্যাচ করছিলাম এবং কেবল কোডের এই টুকরাটিই আমার পক্ষে কাজ করেছিল !! আপনি কি রেডিওগ্রুপের জন্য প্রবাহ বিন্যাস সরবরাহ করতে পারেন?
প্রতীক সলুজা

এছাড়াও, আমি জানতে চাই যে আমি কীভাবে মার্জিন ব্যবহার করতে পারি? মার্জিন = 10 ডিপি লেআউট থেকে সঠিকভাবে আসছে।
প্রতীক সালুজা

4
@ প্রটিক, আপনার যদি একটি ছোট রেডিওগ্রুপ থাকে এবং আপনি চান যে অন্য স্থানগুলি যদি সেখানে থাকে এবং পাশে না থাকে তবে পরবর্তী লাইনে প্রবাহিত থাকে তবে তার পাশে অন্য মতামত প্রদর্শন করা উচিত, ফ্লোএলআউটটি ঠিকঠাক কাজ করা উচিত। একটি বৃহত অনুভূমিক রেডিওগ্রুপ যা প্রথম রেখাটি ঘর থেকে বাইরে চলে যাওয়ার পরে তার রেডিওবটন আইটেমগুলি পরবর্তী লাইনে প্রবাহিত করে, রেডিওগ্রুপ লিনিয়ারলাউট প্রসারিত করার কারণে একটি কাস্টম রেডিওগ্রুপ-ধরণের শ্রেণি লিখতে হবে। আপনি এই ফ্লোএলআউট ক্লাসের ধারণাগুলি ব্যবহার করে একটি কাস্টম রেডিওগ্রুপ শ্রেণি লিখতে পারেন। এখনও অবধি আমার রেডিও বোতাম ব্যবহার করার দরকার পড়েনি। আমরা সাধারণত স্পিনার বা অন্যান্য নিয়ন্ত্রণ ব্যবহার করি।
jk7

@Pratik আপনার সাথে সব মার্জিন সেট করতে পারেন android:layout_margin="10dp"লেআউট ফাইলের মধ্যে, অথবা যেমন বৈশিষ্ট্যাবলী সঙ্গে পৃথক মার্জিন নির্ধারণ করে android:layout_marginLeft="10dp", android:layout_marginTop="4dp", তারতম্য.এটি।
jk7

1

কনস্ট্রেন্টলয়েটে এখন একটি ফ্লো উইজেট ব্যবহার করে সমর্থনে নির্মিত built এটিতে অনেকগুলি বিকল্প রয়েছে যা বিভিন্ন ধরণের প্রবাহ অর্জন করতে ব্যবহার করা যেতে পারে।

উদাহরণ:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.constraintlayout.helper.widget.Flow
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:constraint_referenced_ids="item_1,item_2,item_3"
    app:flow_horizontalBias="0"
    app:flow_horizontalGap="10dp"
    app:flow_horizontalStyle="packed"
    app:flow_verticalGap="8dp"
    app:flow_wrapMode="aligned"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<View
    android:id="@+id/item_1"
    android:layout_width="50dp"
    android:layout_height="50dp" />

<View
    android:id="@+id/item_2"
    android:layout_width="50dp"
    android:layout_height="50dp" />

<View
    android:id="@+id/item_3"
    android:layout_width="50dp"
    android:layout_height="50dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

এই পোস্টে একবার দেখুন: https://medium.com/@tapanrgohil/constraintlayout-flow-bye-bye-to-linerlayout-78fd7fa9b679

এবং এখানে: https://www.bignerdranch.com/blog/constraintlayout-flow-simple-grid-building-without-nested-layouts/


0

এখানে দুর্দান্ত সরল স্ব-অন্তর্ভুক্ত ফ্লোএলআউট কোড (কয়েকটি সংক্ষিপ্ত জিস্ট.github ফাইল) :

http://hzqtc.github.io/2013/12/android-custom-layout-flowlayout.html

তবে বাক্সের বাইরে থাকা ক্রিয়াকলাপটি কাস্টম লেআউটটি লোড করার জন্য আমার পক্ষে কাজ করে নি।

আমি এই কাজের আশেপাশে [2-প্যারাম ব্যবহার করে। ইনফ্লেট () এই উদাহরণ থেকে কল ]] :

@Override
protected void onCreate(Bundle savedInstanceState)
{
    // ..

    setContentView(R.layout.main_res_layout_activity_main);

    ViewGroup flowContainer = getFlowLayoutView(); 

    // ..
}

ViewGroup getFlowLayoutView()
{
    LayoutInflater inflater = getLayoutInflater();

    ViewGroup flowLayout = 
        (ViewGroup)
            inflater.inflate(
                    R.layout.main_res_layout_activity_main,
                    (FlowLayout) findViewById(R.id.flow_container)
            );

    return flowLayout;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.