snapshot on the way to handling rotation of the board view. Pass

orientation changes down to it (or any other interested delegate), and
have it lay its container out again. There appear to be race
conditions here: sometimes the toolbar winds up in the wrong
orientation, and on some devices the board can be blank. One problem
is that on a multi-paned device a single pane may be portrait (taller
than wide) though the whole device is in landscape mode. The big
challege is to get the view's max dimensions (and whether it's
landscape or portrait) when layout hasn't yet begun, because we that
for the jni part of layout. Messy still, but better than before and I
think progress in the right direction.
This commit is contained in:
Eric House 2016-04-04 13:43:16 -07:00
parent b6431f0373
commit ae8a66f37b
8 changed files with 146 additions and 70 deletions

View file

@ -596,6 +596,7 @@ public class BoardDelegate extends DelegateBase
m_timers = new TimerRunnable[4]; // needs to be in sync with
// XWTimerReason
m_view = (BoardView)findViewById( R.id.board_view );
m_view.setBoardDelegate( this );
if ( ! ABUtils.haveActionBar() ) {
m_tradeButtons = findViewById( R.id.exchange_buttons );
if ( null != m_tradeButtons ) {
@ -752,6 +753,26 @@ public class BoardDelegate extends DelegateBase
}
}
@Override
public void orientationChanged()
{
boolean isPortrait = isPortrait();
DbgUtils.logdf( "BoardDelegate.orientationChanged(isPortrait=%b)",
isPortrait );
positionToolbar( isPortrait );
m_view.orientationChanged();
}
private void positionToolbar( boolean isPortrait )
{
if ( null != findViewById( R.id.tbar_parent_hor ) ) {
if ( null == m_toolbar ) {
m_toolbar = new Toolbar( m_activity, this );
}
m_toolbar.setIsPortrait( isPortrait );
}
}
protected boolean onKeyDown( int keyCode, KeyEvent event )
{
boolean handled = false;
@ -2155,12 +2176,7 @@ public class BoardDelegate extends DelegateBase
setTitle( GameUtils.getName( m_activity, m_rowid ) );
}
if ( null != findViewById( R.id.tbar_parent_hor ) ) {
int orient = m_activity.getResources().getConfiguration().orientation;
boolean isLandscape = Configuration.ORIENTATION_LANDSCAPE == orient;
m_toolbar = new Toolbar( m_activity, this, isLandscape );
}
positionToolbar( isPortrait() );
populateToolbar();
adjustTradeVisibility();

View file

@ -55,6 +55,7 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
private static final int PINCH_THRESHOLD = 40;
private Context m_context;
private BoardDelegate m_boardDlgt;
private int m_defaultFontHt;
private int m_mediumFontHt;
private Runnable m_invalidator;
@ -142,33 +143,21 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
return wantMore; // true required to get subsequent events
}
// private void printMode( String comment, int mode )
// {
// comment += ": ";
// switch( mode ) {
// case View.MeasureSpec.AT_MOST:
// comment += "AT_MOST";
// break;
// case View.MeasureSpec.EXACTLY:
// comment += "EXACTLY";
// break;
// case View.MeasureSpec.UNSPECIFIED:
// comment += "UNSPECIFIED";
// break;
// default:
// comment += "<bogus>";
// }
// DbgUtils.logf( comment );
// }
@Override
protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec )
{
// One of the android sample apps ignores mode entirely:
// int w = MeasureSpec.getSize(widthMeasureSpec);
// int h = MeasureSpec.getSize(heightMeasureSpec);
// int d = w == 0 ? h : h == 0 ? w : w < h ? w : h;
// setMeasuredDimension(d, d);
// DbgUtils.logf( "onMeasure(width: %s, height: %s)",
// MeasureSpec.toString( widthMeasureSpec ),
// MeasureSpec.toString( heightMeasureSpec ) );
if ( null != m_dims ) {
if ( m_boardDlgt.isPortrait() != (m_dims.height > m_dims.width) ) {
// square possible; will break above!
Assert.assertTrue( m_dims.height != m_dims.width );
// DbgUtils.logf( "onMeasure: discarding m_dims" );
m_dims = null;
}
}
int width, height;
m_measuredFromDims = null != m_dims;
@ -189,8 +178,17 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
width = minWidth;
}
setMeasuredDimension( width, height );
DbgUtils.logdf( "BoardView.onMeasure: calling setMeasuredDimension( width=%d, height=%d )",
width, height );
}
// public void onSizeChanged( int width, int height, int oldWidth, int oldHeight )
// {
// DbgUtils.logf( "BoardView.onSizeChanged(): width: %d => %d; height: %d => %d",
// oldWidth, width, oldHeight, height );
// super.onSizeChanged( width, height, oldWidth, oldHeight );
// }
// This will be called from the UI thread
@Override
protected void onDraw( Canvas canvas )
@ -268,6 +266,11 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
return layoutDone;
} // layoutBoardOnce
protected void setBoardDelegate( BoardDelegate dlgt )
{
m_boardDlgt = dlgt;
}
// BoardHandler interface implementation
public void startHandling( Activity parent, JNIThread thread,
XwJNI.GamePtr gamePtr, CurGameInfo gi,
@ -334,6 +337,12 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
});
}
protected void orientationChanged()
{
m_dims = null;
requestLayout();
}
public void setInTrade( boolean inTrade )
{
if ( null != m_canvas ) {

View file

@ -19,6 +19,7 @@
package org.eehouse.android.xw4;
import android.graphics.Rect;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
@ -86,7 +87,8 @@ public class DelegateBase implements DlgClickNotify,
protected void onDestroy() {}
protected void onWindowFocusChanged( boolean hasFocus ) {}
protected boolean onBackPressed() { return false; }
public void orientationChanged() {}
protected void requestWindowFeature( int feature ) {}
// Fragments only
@ -232,6 +234,29 @@ public class DelegateBase implements DlgClickNotify,
}
}
protected boolean isPortrait()
{
int[] containerDims = new int[2];
getContainerDims( containerDims );
boolean result = containerDims[0] < containerDims[1];
DbgUtils.logdf( "%s.isPortrait() => %b", getClass().getName(), result );
return result;
}
protected void getContainerDims( int[] outDims )
{
if ( m_activity instanceof FragActivity ) {
((FragActivity)m_activity).getFragmentDims( outDims );
} else {
Rect rect = new Rect();
m_rootView.getWindowVisibleDisplayFrame( rect );
outDims[0] = rect.width();
outDims[1] = rect.height();
}
DbgUtils.logdf( "getContainerDims(): width => %d, height => %d",
outDims[0], outDims[1] );
}
protected String getString( int resID, Object... params )
{
return LocUtils.getString( m_activity, resID, params );

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2014 by Eric House (xwords@eehouse.org). All rights
* Copyright 2014-2016 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
@ -20,6 +20,7 @@
package org.eehouse.android.xw4;
import android.graphics.Rect;
import android.app.Dialog;
import android.content.res.Configuration;
import android.os.Bundle;
@ -39,8 +40,10 @@ import junit.framework.Assert;
public class FragActivity extends FragmentActivity
implements FragmentManager.OnBackStackChangedListener {
private static final int MAX_PANES_LANDSCAPE = 2;
public interface OrientChangeListener {
void orientationChanged( int orientation );
void orientationChanged();
}
private static FragActivity s_this;
@ -79,17 +82,35 @@ public class FragActivity extends FragmentActivity
@Override
public void onConfigurationChanged( Configuration newConfig )
{
int orientation = newConfig.orientation;
boolean isPortrait = orientation == Configuration.ORIENTATION_PORTRAIT;
int maxPanes = isPortrait? 1 : 2;
Rect rect = new Rect();
m_root.getWindowVisibleDisplayFrame( rect );
// DbgUtils.logf( "FragActivity.onConfigurationChanged(): width=%d; height=%d",
// rect.width(), rect.height());
boolean isPortrait
= Configuration.ORIENTATION_PORTRAIT == newConfig.orientation;
if ( isPortrait != (rect.width() <= rect.height()) ) {
DbgUtils.logdf( "FragActivity.onConfigurationChanged(): isPortrait:"
+ " %b; width: %d; height: %d",
isPortrait, rect.width(), rect.height() );
}
int maxPanes = isPortrait? 1 : MAX_PANES_LANDSCAPE;
if ( m_maxPanes != maxPanes ) {
m_maxPanes = maxPanes;
setVisiblePanes();
tellOrientationChanged( orientation );
}
tellOrientationChanged();
super.onConfigurationChanged( newConfig );
}
protected void getFragmentDims( int[] dims )
{
Rect rect = new Rect();
m_root.getWindowVisibleDisplayFrame( rect );
dims[0] = rect.width() / Math.min( m_maxPanes, m_root.getChildCount() );
dims[1] = rect.height();
}
@Override
protected Dialog onCreateDialog( int id )
{
@ -225,7 +246,7 @@ public class FragActivity extends FragmentActivity
}
// Walk all Fragment children and if they care notify of change.
private void tellOrientationChanged( int orientation )
private void tellOrientationChanged()
{
FragmentManager fm = getSupportFragmentManager();
int nPanes = m_root.getChildCount();
@ -236,7 +257,7 @@ public class FragActivity extends FragmentActivity
if ( null == frag ) {
DbgUtils.logf( "tellOrienationChanged: NO FRAG at %d, id=%d", ii, id );
} else if ( frag instanceof OrientChangeListener ) {
((OrientChangeListener)frag).orientationChanged( orientation );
((OrientChangeListener)frag).orientationChanged();
}
}
}

View file

@ -28,7 +28,7 @@ import junit.framework.Assert;
// obtainable when other read locks are granted but not when a
// write lock is. Write-locks are exclusive.
public class GameLock {
private static final boolean DEBUG_LOCKS = true;
private static final boolean DEBUG_LOCKS = false;
private static final int SLEEP_TIME = 100;
private static final long ASSERT_TIME = 2000;
private long m_rowid;

View file

@ -72,17 +72,12 @@ public class Toolbar {
private DlgDelegate.HasDlgDelegate m_dlgDlgt;
private LinearLayout m_layout;
private boolean m_visible;
private Boolean m_isPortrait;
private enum ORIENTATION { ORIENT_PORTRAIT, ORIENT_LANDSCAPE };
private ORIENTATION m_curOrient = null;
public Toolbar( Activity activity, HasDlgDelegate dlgDlgt,
boolean isLandscape )
public Toolbar( Activity activity, HasDlgDelegate dlgDlgt )
{
m_activity = activity;
m_dlgDlgt = dlgDlgt;
setIsLandscape( isLandscape );
}
public void setVisible( boolean visible )
@ -123,18 +118,10 @@ public class Toolbar {
setLongClickListener( index, listener );
}
private void setIsLandscape( boolean landscape )
protected void setIsPortrait( boolean isPortrait )
{
if ( landscape && m_curOrient == ORIENTATION.ORIENT_LANDSCAPE ) {
// do nothing
} else if ( !landscape && m_curOrient == ORIENTATION.ORIENT_PORTRAIT ) {
// do nothing
} else {
if ( landscape ) {
m_curOrient = ORIENTATION.ORIENT_LANDSCAPE;
} else {
m_curOrient = ORIENTATION.ORIENT_PORTRAIT;
}
if ( null == m_isPortrait || m_isPortrait != isPortrait ) {
m_isPortrait = isPortrait;
doShowHide();
}
}
@ -151,20 +138,21 @@ public class Toolbar {
private void doShowHide()
{
Assert.assertTrue( null != m_curOrient );
boolean isLandscape = ORIENTATION.ORIENT_LANDSCAPE == m_curOrient;
Assert.assertTrue( null != m_isPortrait );
if ( null == m_layout ) {
m_layout = (LinearLayout)LocUtils.inflate( m_activity, R.layout.toolbar );
m_layout.setOrientation(ORIENTATION.ORIENT_PORTRAIT == m_curOrient
? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL );
} else {
((ViewGroup)m_layout.getParent()).removeView( m_layout );
}
m_layout.setOrientation( m_isPortrait ?
LinearLayout.HORIZONTAL : LinearLayout.VERTICAL );
int id = isLandscape ? R.id.tbar_parent_vert : R.id.tbar_parent_hor;
ViewGroup scroller = (ViewGroup)m_activity.findViewById( id );
if ( null != scroller ) {
// Google's had reports of a crash adding second view
scroller.removeAllViews();
scroller.addView( m_layout ); // failing
}
int id = m_isPortrait ? R.id.tbar_parent_hor : R.id.tbar_parent_vert;
ViewGroup scroller = (ViewGroup)m_activity.findViewById( id );
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 );

View file

@ -22,6 +22,7 @@ package org.eehouse.android.xw4;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextMenu;
@ -178,6 +179,13 @@ public class XWActivity extends Activity implements Delegator {
m_dlgt.prepareDialog( DlgID.values()[id], dialog );
}
@Override
public void onConfigurationChanged( Configuration newConfig )
{
m_dlgt.orientationChanged();
super.onConfigurationChanged( newConfig );
}
@Override
protected void onActivityResult( int requestCode, int resultCode,
Intent data )

View file

@ -20,6 +20,7 @@
package org.eehouse.android.xw4;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
@ -33,7 +34,9 @@ import android.widget.ListView;
import junit.framework.Assert;
public class XWFragment extends Fragment implements Delegator {
public class XWFragment extends Fragment
implements Delegator,
FragActivity.OrientChangeListener {
private DelegateBase m_dlgt;
@ -122,6 +125,12 @@ public class XWFragment extends Fragment implements Delegator {
Assert.fail();
}
// FragActivity.OrientChangeListener
public void orientationChanged()
{
m_dlgt.orientationChanged();
}
public ListView getListView()
{
ListView view = (ListView)m_dlgt.findViewById( android.R.id.list );