From 2a8ce27ca90aebad5cc65a59042f2994665f4a02 Mon Sep 17 00:00:00 2001 From: Eric House Date: Thu, 18 Aug 2016 11:30:32 -0700 Subject: [PATCH] make custom layout better on old android version tweaks to BoardContainer and Toolbar to better position toolbar and better hide/show it in tile exchange mode. The bar's still partially offscreen sometimes on a 2.3.7 emulator but it's usable. Next I need to try specifying the size of the bar rather than having it derive from the size of the images it contains. --- .../src/org/eehouse/android/xw4/ABUtils.java | 4 +- .../eehouse/android/xw4/BoardContainer.java | 136 ++++++++++++------ .../src/org/eehouse/android/xw4/Toolbar.java | 20 +-- 3 files changed, 105 insertions(+), 55 deletions(-) diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/ABUtils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/ABUtils.java index 500b25667..98037a7f7 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/ABUtils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/ABUtils.java @@ -69,7 +69,9 @@ public class ABUtils { public static boolean haveActionBar() { - return null != s_safeInval; + boolean result = null != s_safeInval; + // DbgUtils.logf( "haveActionBar() => %b", result ); + return result; } // http://stackoverflow.com/questions/10929579/how-to-check-if-android-phone-has-hardware-menu-button-in-android-2-1: diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardContainer.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardContainer.java index 72e2928ad..0a3e7bf06 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardContainer.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardContainer.java @@ -26,12 +26,22 @@ import android.util.AttributeSet; import android.widget.LinearLayout; import android.view.ViewGroup; import android.view.View; +import android.view.View.MeasureSpec; +import android.graphics.Rect; import junit.framework.Assert; public class BoardContainer extends ViewGroup { - private static final int TBAR_PCT_HOR = 90; - private static final int TBAR_PCT_VERT = 85; + // If the ratio of height/width exceeds this, use portrait layout + private static final int PORTRAIT_THRESHHOLD = 105; + + private static final int BOARD_PCT_HOR = 90; + private static final int BOARD_PCT_VERT = 85; + + private static final int BOARD_INDX = 0; + private static final int EXCH_INDX = 1; + private static final int VBAR_INDX = 2; + private static final int HBAR_INDX = 3; private static boolean s_isPortrait = true; // initial assumption private static int s_width = 0; @@ -59,23 +69,29 @@ public class BoardContainer extends ViewGroup { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int childCount = getChildCount(); - Assert.assertTrue( 4 == childCount ); - - int width = View.MeasureSpec.getSize( widthMeasureSpec ); - int height = View.MeasureSpec.getSize( heightMeasureSpec ); + int width = MeasureSpec.getSize( widthMeasureSpec ); + int height = MeasureSpec.getSize( heightMeasureSpec ); if ( 0 != width || 0 != height ) { setForPortrait( width, height ); - } - for ( int ii = 0; ii < childCount; ii++ ) { - final View child = getChildAt( ii ); - if ( GONE != child.getVisibility() ) { - // Measure the child. - measureChild( child, widthMeasureSpec, heightMeasureSpec ); + Rect[] rects = figureBounds( 0, 0, width, height ); + + // Measure the board + measureChild( BOARD_INDX, rects[0] ); + + int childCount = getChildCount(); + if ( 1 < childCount ) { + Assert.assertTrue( 4 == childCount ); + + if ( haveTradeBar() ) { + // Measure the exchange buttons bar + measureChild( EXCH_INDX, rects[1] ); + } + + // Measure the toolbar + measureChild( s_isPortrait ? HBAR_INDX : VBAR_INDX, rects[1] ); } } - setMeasuredDimension( width, height ); } @@ -85,37 +101,42 @@ public class BoardContainer extends ViewGroup { protected void onLayout( boolean changed, int left, int top, int right, int bottom) { - boolean haveTradeBar - = GONE != findViewById(R.id.exchange_buttons).getVisibility(); - int boardHt = bottom - top; - if ( haveTradeBar || s_isPortrait ) { - boardHt = boardHt * TBAR_PCT_HOR / 100; - } - int boardWidth = right - left; - if ( !s_isPortrait ) { - boardWidth = boardWidth * TBAR_PCT_VERT / 100; - } + Rect[] rects = figureBounds( left, top, right, bottom ); // layout the board - BoardView board = (BoardView)getChildAt( 0 ); - board.layout( left, top, left + boardWidth, top + boardHt ); + BoardView board = (BoardView)getChildAt( BOARD_INDX ); + layoutChild( board, rects[0] ); - // The trade bar - if ( haveTradeBar ) { - LinearLayout exchButtons = (LinearLayout)getChildAt( 1 ); - Assert.assertTrue( exchButtons.getId() == R.id.exchange_buttons ); - exchButtons.layout( left, top + boardHt, right, bottom ); - } + if ( 1 < getChildCount() ) { - // Now one of the toolbars - View scrollView = getChildAt( s_isPortrait ? 3 : 2 ); - Assert.assertTrue( GONE != scrollView.getVisibility() ); - if ( s_isPortrait ) { - top += boardHt; - } else { - left += boardWidth; + // The trade bar + if ( haveTradeBar() ) { + LinearLayout exchButtons = (LinearLayout)getChildAt( EXCH_INDX ); + Assert.assertTrue( exchButtons.getId() == R.id.exchange_buttons ); + layoutChild( exchButtons, rects[1] ); + } + + // Now one of the toolbars + View scrollView = getChildAt( s_isPortrait ? HBAR_INDX : VBAR_INDX ); + if ( GONE != scrollView.getVisibility() ) { + layoutChild( scrollView, rects[1] ); + } } - scrollView.layout( left, top, right, bottom ); + } + + private void measureChild( int index, Rect rect ) + { + int childWidthSpec = MeasureSpec.makeMeasureSpec(rect.width(), + MeasureSpec.AT_MOST ); + int childHeightSpec = MeasureSpec.makeMeasureSpec(rect.height(), + MeasureSpec.AT_MOST ); + View view = getChildAt( index ); + measureChild( view, childWidthSpec, childHeightSpec ); + } + + private void layoutChild( View child, Rect rect ) + { + child.layout( rect.left, rect.top, rect.right, rect.bottom ); } private void setForPortrait( final int width, final int height ) @@ -123,7 +144,7 @@ public class BoardContainer extends ViewGroup { if ( height != s_height || width != s_width ) { s_height = height; s_width = width; - s_isPortrait = height > width; + s_isPortrait = PORTRAIT_THRESHHOLD < (height*100) / width; findViewById( R.id.tbar_parent_hor ) .setVisibility( s_isPortrait ? VISIBLE : GONE ); findViewById( R.id.tbar_parent_vert ) @@ -133,6 +154,39 @@ public class BoardContainer extends ViewGroup { } } + private Rect[] figureBounds( int left, int top, int width, int height ) + { + int boardHeight = ( haveTradeBar() || s_isPortrait) + ? height * BOARD_PCT_HOR / 100 : height; + int boardWidth = s_isPortrait ? width : width * BOARD_PCT_VERT / 100; + + // board + Rect boardBounds = new Rect( left, top, left + boardWidth, + top + boardHeight ); + // DbgUtils.logf( "BoardContainer: boardBounds: %s", boardBounds.toString() ); + // toolbar + if ( s_isPortrait ) { + top += boardHeight; + height -= boardHeight; + } else { + left += boardWidth; + width -= boardWidth; + } + Rect toolsBounds = new Rect( left, top, left + width, top + height ); + // DbgUtils.logf( "BoardContainer: toolsBounds: %s", toolsBounds.toString() ); + return new Rect[] { boardBounds, toolsBounds }; + } + + private boolean haveTradeBar() + { + boolean result = false; + if ( s_isPortrait && 1 < getChildCount() ) { + View bar = getChildAt( 1 ); + result = null != bar && GONE != bar.getVisibility(); + } + return result; + } + private static void callSCL() { if ( 0 != s_width || 0 != s_height ) { diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/Toolbar.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/Toolbar.java index 496007e4a..3d3c79351 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/Toolbar.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/Toolbar.java @@ -81,7 +81,7 @@ public class Toolbar implements BoardContainer.SizeChangeListener { { if ( m_visible != visible ) { m_visible = visible; - doShowHide( null ); + doShowHide(); } } @@ -134,10 +134,9 @@ public class Toolbar implements BoardContainer.SizeChangeListener { // SizeChangeListener public void sizeChanged( int width, int height, boolean isPortrait ) { - DbgUtils.logf( "Toolbar.sizeChanged(isPortrait=%b)", isPortrait ); tryAddListeners( m_onClickListeners ); tryAddListeners( m_onLongClickListeners ); - doShowHide( new Boolean(isPortrait) ); + doShowHide(); } private void tryAddListeners( Map map ) @@ -168,14 +167,10 @@ public class Toolbar implements BoardContainer.SizeChangeListener { return success; } - private void doShowHide( Boolean shouldBePortrait ) + private void doShowHide() { - // BoardContainer owns which scroller we'll use, and signals its - // choice by setting their visibility. We use the one that's visible. - boolean isPortrait = View.GONE != m_scrollHor.getVisibility(); - DbgUtils.logf( "Toolbar.doShowHide(): isPortrait: %b", isPortrait ); - Assert.assertTrue( null == shouldBePortrait - || shouldBePortrait.equals(isPortrait) ); + boolean isPortrait = BoardContainer.getIsPortrait(); + DbgUtils.logdf( "Toolbar.doShowHide(): isPortrait: %b", isPortrait ); if ( null == m_layout ) { m_layout = (LinearLayout)LocUtils.inflate( m_activity, R.layout.toolbar ); @@ -186,13 +181,12 @@ public class Toolbar implements BoardContainer.SizeChangeListener { LinearLayout.HORIZONTAL : LinearLayout.VERTICAL ); ViewGroup scroller = isPortrait ? m_scrollHor : m_scrollVert; - Assert.assertNotNull( scroller ); if ( null != scroller ) { // Google's had reports of a crash adding second view scroller.removeAllViews(); scroller.addView( m_layout ); - } - m_layout.setVisibility( m_visible? View.VISIBLE : View.GONE ); + scroller.setVisibility( m_visible? View.VISIBLE : View.GONE ); + } } }