Segmented control in Android
Asked Answered
E

5

11

I need to use IPhone like segmented control in Android. Is there a default control for the same? What might be the best and efficient way to do so?

Eba answered 10/6, 2011 at 4:49 Comment(3)
duplicate of #3953491Genesisgenet
Possible duplicate of Segment control in androidInaugurate
I'm dumbfounded that this was not a foundational element in Android development. Such a basic common element. And, AFAICT, still not available in 2023? Is that possible? Embarrassing.Succuss
E
-2

You can achieve segmented control functionality with Radio Group

Here are few examples this and Hello Form

Earthshaking answered 10/6, 2011 at 5:20 Comment(1)
such an uninspired answer doesn't deserve to be the accepted answer! Btw. the links don't work anymore.Argot
B
9

What you are looking for is MaterialButtonToggleGroup, and you can put in some Material Button. It is pretty similar to iOS UISegmentContorol.

It looks like this: enter image description here

source with example: https://material.io/develop/android/components/buttons#toggle-button

Buhl answered 7/6, 2020 at 9:25 Comment(2)
an other example of its usage journaldev.com/31950/android-materialbuttontogglegroupBuhl
Is it possible to have a slide animation on it?Sanitize
E
5

I have achieved it using build in Views.

MySegmentActivity

public class SegmentActivity extends AppCompatActivity implements View.OnClickListener {

    private Context mContext;
    private List<Button> buttonList = null;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.item_segment_layout);

        mContext = SegmentActivity.this;
        initSegmentButtons();
    }

    private void initSegmentButtons() {

        buttonList = new ArrayList<>();

        Button dayBtn = (Button) findViewById(R.id.btn_day);
        Button weekBtn = (Button) findViewById(R.id.btn_week);
        Button monthBtn = (Button) findViewById(R.id.btn_month);

        dayBtn.setOnClickListener(this);
        weekBtn.setOnClickListener(this);
        monthBtn.setOnClickListener(this);

        buttonList.add(dayBtn);
        buttonList.add(weekBtn);
        buttonList.add(monthBtn);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_day:
                buttonList.get(0).setBackgroundResource(R.drawable.btn_bg_orange_selected);
                buttonList.get(1).setBackgroundResource(R.drawable.btn_bg_orange);
                buttonList.get(2).setBackgroundResource(R.drawable.btn_bg_orange);
                break;
            case R.id.btn_week:
                buttonList.get(0).setBackgroundResource(R.drawable.btn_bg_orange);
                buttonList.get(1).setBackgroundResource(R.drawable.btn_bg_orange_selected);
                buttonList.get(2).setBackgroundResource(R.drawable.btn_bg_orange);
                break;
            case R.id.btn_month:
                buttonList.get(0).setBackgroundResource(R.drawable.btn_bg_orange);
                buttonList.get(1).setBackgroundResource(R.drawable.btn_bg_orange);
                buttonList.get(2).setBackgroundResource(R.drawable.btn_bg_orange_selected);
                break;
            default:
                break;
        }
    }
}

layout.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="@dimen/activity_horizontal_margin"
    android:layout_marginRight="@dimen/activity_horizontal_margin"
    android:orientation="horizontal">

    <Button
        android:id="@+id/btn_day"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/btn_bg_orange"
        android:gravity="center"
        android:text="Day"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

    <Button
        android:id="@+id/btn_week"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="-1dp"
        android:layout_marginRight="-1dp"
        android:layout_weight="1"
        android:background="@drawable/btn_bg_orange"
        android:gravity="center"
        android:text="Week"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

    <Button
        android:id="@+id/btn_month"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/btn_bg_orange_selected"
        android:gravity="center"
        android:text="Month"
        android:textColor="@android:color/white"
        android:textSize="20sp" />
</LinearLayout>

btn_bg_orange.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <stroke
        android:width="1dp"
        android:color="@color/orange" />

    <solid android:color="@android:color/transparent" />
</shape>

btn_bg_orange_selected

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <stroke
        android:width="1dp"
        android:color="@color/orange" />

    <solid android:color="@color/orange" />
</shape>
Elfont answered 28/12, 2016 at 12:1 Comment(0)
L
2

For a modern iOS-styled SegmentedControl, you can consider using: https://github.com/alanvan0502/segmented-control-group

Lignite answered 16/9, 2020 at 10:13 Comment(1)
This one is best. But my existing project is using Android Support Library. Where using your suggestion is forcing me to migrate to AndroidX. Which is big headache.Bottle
E
0

I have created a SegmentCustomControl for Android.

SegmentTestActivity.class

public class SegmentTestActivity extends AppCompatActivity {

    private Context mContext;
    private SegmentView segmentView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.segment_test_activity);

        mContext = SegmentTestActivity.this;

        segmentView = (SegmentView) findViewById(R.id.segment_view);
        segmentView.setOnSegmentSelectedListener(new OnSegmentSelectedListener() {
            @Override
            public void onSegmentSelected(int position) {
                Toast.makeText(mContext, "Segment selected at Index : " + position, Toast.LENGTH_SHORT).show();
            }
        });

    }
}

segment_test_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">

    <custom.rnd.SegmentView
        android:id="@+id/segment_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:numberOfSegment="3"
        app:segmentColor="@color/colorPrimary"
        app:selectedTextColor="@android:color/black"
        app:textSize="16sp"
        app:unSelectedTextColor="@color/colorPrimary" />

    <custom.rnd.SegmentView
        android:id="@+id/segment_view2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:gravity="center"
        app:numberOfSegment="2"
        app:segmentColor="@color/colorAccent"
        app:selectedTextColor="@android:color/black"
        app:titlesOfSegment="New,OLD"
        app:unSelectedTextColor="@android:color/white" />

</RelativeLayout>

SegmentView

public class SegmentView extends LinearLayout{

    public static final String TAG = "SegmentView";
    private OnSegmentSelectedListener onSegmentSelectedListener;
    private SegmentView segmentView;
    private int numberOfSegments = 0;
    private List<String> titlesOfSegment;
    private int selectedTextColor;
    private int unSelectedTextColor;
    private int segmentColorSelected;
    /*private int defaultSelectedColor = Color.parseColor("#c13d1f");
    private int defaultUnSelectedColor = Color.parseColor("#ea8d21");*/

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

    public SegmentView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initLayout(context, attrs);
    }

    private void initLayout(Context mContext, AttributeSet attrs) {
        segmentView = this;

        titlesOfSegment = new ArrayList<>();

        TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.SegmentView);
        numberOfSegments = typedArray.getInt(R.styleable.SegmentView_numberOfSegment, 0);
        String titleWithComma = typedArray.getString(R.styleable.SegmentView_titlesOfSegment);
        selectedTextColor = typedArray.getColor(R.styleable.SegmentView_selectedTextColor, Color.WHITE);
        unSelectedTextColor = typedArray.getColor(R.styleable.SegmentView_unSelectedTextColor, Color.parseColor("#c13d1f"));
        segmentColorSelected = typedArray.getColor(R.styleable.SegmentView_segmentColor, 0);

        //orientation = typedArray.getInt(R.styleable.SegmentView_orientation , 0);

        int unitsTextSize = typedArray.getDimensionPixelSize(R.styleable.SegmentView_textSize, 0);

        if (titleWithComma != null && !titleWithComma.isEmpty()) {
            String[] arrayOfTitles = titleWithComma.split(",");
            for (String x : arrayOfTitles) {
                titlesOfSegment.add(x);
            }
        }
        typedArray.recycle();

        segmentView.setOrientation(HORIZONTAL);

        /*if(orientation == 0){
            segmentView.setOrientation(HORIZONTAL);
        }
        else{
            segmentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
            segmentView.setOrientation(VERTICAL);
        }*/

        for (int i = 0; i < numberOfSegments; i++) {

            LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 1.0f);

            /*if(orientation != 0)
                param = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT,1.0f);*/

            Button btn = new Button(mContext);

            if (titlesOfSegment != null && titlesOfSegment.size() == numberOfSegments)
                btn.setText(titlesOfSegment.get(i));
            else
                btn.setText("Segment " + i);
            btn.setTextColor(Color.WHITE);

            if(unitsTextSize != 0){
                btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, unitsTextSize);
            }
            else
                btn.setTextSize(14.0f);

            if (i == 0) {
                btn.setBackgroundResource(R.drawable.btn_bg_orange_selected);
                btn.setTextColor(selectedTextColor);
                updateBorderAndSolidColor(btn);

            } else {
                btn.setBackgroundResource(R.drawable.btn_bg_orange);
                btn.setTextColor(unSelectedTextColor);

                if (segmentColorSelected != 0) {
                    //changeSolidColor(btn ,segmentColorUnSelected);
                    changeStrokeColor(btn, segmentColorSelected);
                }
            }

            final int x = i;
            btn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (onSegmentSelectedListener != null)
                        onSegmentSelectedListener.onSegmentSelected(x);
                    handleClick(x, view);

                }
            });
            segmentView.addView(btn, param);
        }
    }

    private void updateBorderAndSolidColor(Button btn) {
        if (segmentColorSelected != 0) {
            changeStrokeColor(btn, segmentColorSelected);
        }
        if (segmentColorSelected != 0) {
            changeSolidColor(btn, segmentColorSelected);
        }
    }

    public void setOnSegmentSelectedListener(OnSegmentSelectedListener onSegmentSelectedListener) {
        this.onSegmentSelectedListener = onSegmentSelectedListener;
    }


    private void handleClick(int position, View view) {
        Button btnView = null;

        for (int iter = 0; iter < segmentView.getChildCount(); iter++) {
            btnView = (Button) segmentView.getChildAt(iter);
            if (iter == position) {
                btnView.setBackgroundResource(R.drawable.btn_bg_orange_selected);
                btnView.setTextColor(selectedTextColor);
                updateBorderAndSolidColor(btnView);
            } else {
                btnView.setBackgroundResource(R.drawable.btn_bg_orange);
                btnView.setTextColor(unSelectedTextColor);
                if (segmentColorSelected != 0)
                    changeStrokeColor(btnView, segmentColorSelected);
            }
        }
    }

    private void changeStrokeColor(Button view, int colorCode) {
        GradientDrawable drawable = (GradientDrawable) view.getBackground();
        //update value 3 according to your need.
        drawable.setStroke(3, colorCode); // set stroke width and stroke color
    }

    private void changeSolidColor(Button view, int colorCode) {
        GradientDrawable drawable = (GradientDrawable) view.getBackground();
        drawable.setColor(colorCode); // set solid color
    }
}

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="SegmentView">
        <attr name="numberOfSegment" format="integer" />
        <attr name="titlesOfSegment" format="string" />
        <attr name="selectedTextColor" format="color" />
        <attr name="unSelectedTextColor" format="color" />
        <attr name="segmentColor" format="color" />
        <attr name="textSize" format="dimension" />

        <!--<attr name="orientation">
            <enum name="horizontal" value="0" />
            <enum name="vertical" value="1" />
        </attr>-->
    </declare-styleable>
</resources>

and Listener

public interface OnSegmentSelectedListener {
    void onSegmentSelected(int position);
}
Elfont answered 29/12, 2016 at 10:23 Comment(0)
E
-2

You can achieve segmented control functionality with Radio Group

Here are few examples this and Hello Form

Earthshaking answered 10/6, 2011 at 5:20 Comment(1)
such an uninspired answer doesn't deserve to be the accepted answer! Btw. the links don't work anymore.Argot

© 2022 - 2024 — McMap. All rights reserved.