summaryrefslogtreecommitdiff
path: root/main/src/ui/java/de/blinkt/openvpn/views/MultiLineRadioGroup.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/ui/java/de/blinkt/openvpn/views/MultiLineRadioGroup.java')
-rw-r--r--main/src/ui/java/de/blinkt/openvpn/views/MultiLineRadioGroup.java164
1 files changed, 164 insertions, 0 deletions
diff --git a/main/src/ui/java/de/blinkt/openvpn/views/MultiLineRadioGroup.java b/main/src/ui/java/de/blinkt/openvpn/views/MultiLineRadioGroup.java
new file mode 100644
index 00000000..8296a644
--- /dev/null
+++ b/main/src/ui/java/de/blinkt/openvpn/views/MultiLineRadioGroup.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2012-2018 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package de.blinkt.openvpn.views;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.RadioGroup;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MultiLineRadioGroup extends RadioGroup {
+ private Map<View, Rect> viewRectMap;
+
+ public MultiLineRadioGroup(Context context) {
+ this(context, null);
+ }
+
+ public MultiLineRadioGroup(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ viewRectMap = new HashMap<View, Rect>();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
+ int widthMeasurement = MeasureSpec.getSize(widthMeasureSpec);
+ int heightMeasurement = MeasureSpec.getSize(heightMeasureSpec);
+ switch (getOrientation()){
+ case HORIZONTAL:
+ heightMeasurement = findHorizontalHeight(widthMeasureSpec, heightMeasureSpec);
+ break;
+ case VERTICAL:
+ widthMeasurement = findVerticalWidth(widthMeasureSpec, heightMeasureSpec);
+ break;
+ }
+ setMeasuredDimension(widthMeasurement, heightMeasurement);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ int count = getChildCount();
+ for(int x=0; x < count; ++x) {
+ View button = getChildAt(x);
+ Rect dims = viewRectMap.get(button);
+ button.layout(dims.left, dims.top, dims.right, dims.bottom);
+ }
+ }
+
+ private int findHorizontalHeight(int widthMeasureSpec, int heightMeasureSpec){
+ int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
+ int maxRight = MeasureSpec.getSize(widthMeasureSpec) - getPaddingRight();
+
+ // create MeasureSpecs to accommodate max space that RadioButtons can occupy
+ int newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(maxRight - getPaddingLeft(),
+ MeasureSpec.getMode(widthMeasureSpec));
+ int newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ parentHeight - (getPaddingTop() + getPaddingBottom()),
+ MeasureSpec.getMode(heightMeasureSpec));
+
+ int nextLeft = getPaddingLeft();
+ int nextTop = getPaddingTop();
+ int maxRowHeight = 0;
+ viewRectMap.clear();
+ // measure and find placement for each RadioButton (results to be used in onLayout() stage)
+ int count = getChildCount();
+ for(int x=0; x < count; ++x){
+ View button = getChildAt(x);
+ measureChild(button, newWidthMeasureSpec, newHeightMeasureSpec);
+
+ maxRowHeight = Math.max(maxRowHeight, button.getMeasuredHeight());
+
+ // determine RadioButton placement
+ int nextRight = nextLeft + button.getMeasuredWidth();
+ if(nextRight > maxRight){ // if current button will exceed border on this row ...
+ // ... move to next row
+ nextLeft = getPaddingLeft();
+ nextTop += maxRowHeight;
+
+ // adjust for next row values
+ nextRight = nextLeft + button.getMeasuredWidth();
+ maxRowHeight = button.getMeasuredHeight();
+ }
+
+ int nextBottom = nextTop + button.getMeasuredHeight();
+ viewRectMap.put(button, new Rect(nextLeft, nextTop, nextRight, nextBottom));
+
+ // update nextLeft
+ nextLeft = nextRight;
+ }
+
+ // height of RadioGroup is a natural by-product of placing all the children
+ int idealHeight = nextTop + maxRowHeight + getPaddingBottom();
+ switch(MeasureSpec.getMode(heightMeasureSpec)){
+ case MeasureSpec.UNSPECIFIED:
+ return idealHeight;
+ case MeasureSpec.AT_MOST:
+ return Math.min(idealHeight, parentHeight);
+ case MeasureSpec.EXACTLY:
+ default:
+ return parentHeight;
+ }
+ }
+
+ private int findVerticalWidth(int widthMeasureSpec, int heightMeasureSpec){
+ int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
+ int maxBottom = MeasureSpec.getSize(heightMeasureSpec) - getPaddingBottom();
+
+ // create MeasureSpecs to accommodate max space that RadioButtons can occupy
+ int newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
+ parentWidth - (getPaddingLeft() + getPaddingRight()),
+ MeasureSpec.getMode(widthMeasureSpec));
+ int newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(maxBottom - getPaddingTop(),
+ MeasureSpec.getMode(heightMeasureSpec));
+
+ int nextTop = getPaddingTop();
+ int nextLeft = getPaddingLeft();
+ int maxColWidth = 0;
+ viewRectMap.clear();
+ // measure and find placement for each RadioButton (results to be used in onLayout() stage)
+ int count = getChildCount();
+ for(int x=0; x < count; ++x){
+ View button = getChildAt(x);
+ measureChild(button, newWidthMeasureSpec, newHeightMeasureSpec);
+
+ maxColWidth = Math.max(maxColWidth, button.getMeasuredWidth());
+
+ // determine RadioButton placement
+ int nextBottom = nextTop + button.getMeasuredHeight();
+ if(nextBottom > maxBottom){ // if current button will exceed border for this column ...
+ // ... move to next column
+ nextTop = getPaddingTop();
+ nextLeft += maxColWidth;
+
+ // adjust for next row values
+ nextBottom = nextTop + button.getMeasuredHeight();
+ maxColWidth = button.getMeasuredWidth();
+ }
+
+ int nextRight = nextLeft + button.getMeasuredWidth();
+ viewRectMap.put(button, new Rect(nextLeft, nextTop, nextRight, nextBottom));
+
+ // update nextTop
+ nextTop = nextBottom;
+ }
+
+ // width of RadioGroup is a natural by-product of placing all the children
+ int idealWidth = nextLeft + maxColWidth + getPaddingRight();
+ switch(MeasureSpec.getMode(widthMeasureSpec)){
+ case MeasureSpec.UNSPECIFIED:
+ return idealWidth;
+ case MeasureSpec.AT_MOST:
+ return Math.min(idealWidth, parentWidth);
+ case MeasureSpec.EXACTLY:
+ default:
+ return parentWidth;
+ }
+ }
+} \ No newline at end of file