fix invite dialogs for landscape layout

Scrolling's needed in some cases, and you can't easily put a ListView
inside a ScrollView. So replace the ListView with a LinearLayout whose
contents I manage manually, and wrap the whole layout in a ScrollView.
This commit is contained in:
Eric House 2019-04-04 21:26:24 -07:00
parent 054ac325bb
commit c5efeb283a
7 changed files with 144 additions and 169 deletions

View file

@ -148,7 +148,7 @@ public class BTInviteDelegate extends InviteDelegate {
if ( sPersisted.empty() ) { if ( sPersisted.empty() ) {
scan(); scan();
} else { } else {
updateListAdapter( sPersisted.pairs ); updateList( sPersisted.pairs );
} }
} }
@ -258,7 +258,7 @@ public class BTInviteDelegate extends InviteDelegate {
sPersisted.add( dev.getAddress(), dev.getName() ); sPersisted.add( dev.getAddress(), dev.getName() );
store( m_activity ); store( m_activity );
updateListAdapter( sPersisted.pairs ); updateList( sPersisted.pairs );
tryEnable(); tryEnable();
} }
@ -335,7 +335,7 @@ public class BTInviteDelegate extends InviteDelegate {
store( m_activity ); store( m_activity );
clearChecked(); clearChecked();
updateListAdapter( sPersisted.pairs ); updateList( sPersisted.pairs );
tryEnable(); tryEnable();
break; break;
default: default:

View file

@ -31,6 +31,7 @@ import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ListView; import android.widget.ListView;
@ -49,7 +50,7 @@ import java.util.Set;
import org.eehouse.android.xw4.DBUtils.SentInvitesInfo; import org.eehouse.android.xw4.DBUtils.SentInvitesInfo;
abstract class InviteDelegate extends ListDelegateBase abstract class InviteDelegate extends DelegateBase
implements View.OnClickListener, implements View.OnClickListener,
ViewGroup.OnHierarchyChangeListener { ViewGroup.OnHierarchyChangeListener {
private static final String TAG = InviteDelegate.class.getSimpleName(); private static final String TAG = InviteDelegate.class.getSimpleName();
@ -93,9 +94,8 @@ abstract class InviteDelegate extends ListDelegateBase
protected String m_lastDev; protected String m_lastDev;
protected Button m_inviteButton; protected Button m_inviteButton;
private Activity m_activity; private Activity m_activity;
private ListView m_lv; private LinearLayout m_lv;
private TextView m_ev; private TextView m_ev;
private InviteItemsAdapter m_adapter;
protected Map<InviterItem, Integer> m_counts; protected Map<InviterItem, Integer> m_counts;
protected Set<InviterItem> m_checked; protected Set<InviterItem> m_checked;
private boolean m_setChecked; private boolean m_setChecked;
@ -145,8 +145,8 @@ abstract class InviteDelegate extends ListDelegateBase
extraView.setVisibility( View.VISIBLE ); extraView.setVisibility( View.VISIBLE );
} }
m_lv = (ListView)findViewById( android.R.id.list ); m_lv = (LinearLayout)findViewById( R.id.invitees );
m_ev = (TextView)findViewById( android.R.id.empty ); m_ev = (TextView)findViewById( R.id.empty );
if ( null != m_lv && null != m_ev && 0 != emptyMsgId ) { if ( null != m_lv && null != m_ev && 0 != emptyMsgId ) {
m_ev.setText( getString( emptyMsgId ) ); m_ev.setText( getString( emptyMsgId ) );
m_lv.setOnHierarchyChangeListener( this ); m_lv.setOnHierarchyChangeListener( this );
@ -183,17 +183,19 @@ abstract class InviteDelegate extends ListDelegateBase
tryEnable(); tryEnable();
} }
protected void updateListAdapter( List<? extends InviterItem> items ) protected void updateList( List<? extends InviterItem> items )
{ {
updateListAdapter( R.layout.two_strs_item, items ); updateList( R.layout.two_strs_item, items );
} }
protected void updateListAdapter( int itemId, protected void updateList( int itemId, List<? extends InviterItem> items )
List<? extends InviterItem> items )
{ {
updateChecked( items ); updateChecked( items );
m_adapter = new InviteItemsAdapter( itemId, items );
setListAdapter( m_adapter ); m_lv.removeAllViews();
for ( InviterItem item : items ) {
m_lv.addView( makeViewFor( itemId, item ) );
}
} }
protected void listSelected( InviterItem[] selected, String[] devs ) protected void listSelected( InviterItem[] selected, String[] devs )
@ -244,10 +246,13 @@ abstract class InviteDelegate extends ListDelegateBase
//////////////////////////////////////// ////////////////////////////////////////
// ViewGroup.OnHierarchyChangeListener // ViewGroup.OnHierarchyChangeListener
//////////////////////////////////////// ////////////////////////////////////////
@Override
public void onChildViewAdded( View parent, View child ) public void onChildViewAdded( View parent, View child )
{ {
showEmptyIfEmpty(); showEmptyIfEmpty();
} }
@Override
public void onChildViewRemoved( View parent, View child ) public void onChildViewRemoved( View parent, View child )
{ {
showEmptyIfEmpty(); showEmptyIfEmpty();
@ -255,8 +260,8 @@ abstract class InviteDelegate extends ListDelegateBase
private void showEmptyIfEmpty() private void showEmptyIfEmpty()
{ {
m_ev.setVisibility( 0 == m_lv.getChildCount() int count = m_lv.getChildCount();
? View.VISIBLE : View.GONE ); m_ev.setVisibility( 0 == count ? View.VISIBLE : View.GONE );
} }
protected void tryEnable() protected void tryEnable()
@ -297,105 +302,69 @@ abstract class InviteDelegate extends ListDelegateBase
} }
} }
private InviteItemsAdapter getAdapter() private View makeViewFor( int itemID, final InviterItem item )
{ {
return m_adapter; final LinearLayout layout = (LinearLayout)
} inflate( R.layout.inviter_item_frame );
CheckBox box = (CheckBox)layout.findViewById( R.id.inviter_check );
private class InviteItemsAdapter extends XWListAdapter { // Give subclass a chance to install and populate its view
private InviterItem[] m_items; FrameLayout frame = (FrameLayout)layout.findViewById( R.id.frame );
private int m_itemId; View child = inflate( itemID );
frame.addView( child );
onChildAdded( child, item );
public InviteItemsAdapter( int itemID, List<? extends InviterItem> items ) m_counts.put( item, 1 );
{ if ( XWPrefs.getCanInviteMulti( m_activity ) && 1 < m_nMissing ) {
super( null == items? 0 : items.size() ); Spinner spinner = (Spinner)
m_itemId = itemID; layout.findViewById(R.id.nperdev_spinner);
if ( null != items ) { ArrayAdapter<String> adapter =
m_items = items.toArray( new InviterItem[items.size()] ); new ArrayAdapter<String>( m_activity, android.R.layout
.simple_spinner_item );
for ( int ii = 1; ii <= m_nMissing; ++ii ) {
String str = getQuantityString( R.plurals.nplayers_fmt, ii, ii );
adapter.add( str );
} }
// m_items = new LinearLayout[getCount()]; spinner.setAdapter( adapter );
} spinner.setVisibility( View.VISIBLE );
spinner.setOnItemSelectedListener( new OnItemSelectedListener() {
public InviterItem[] getItems() { return m_items; } public void onItemSelected( AdapterView<?> parent,
View view, int pos,
// public String[] getAddrs() { return m_devAddrs; } long id )
{
@Override m_counts.put( item, 1 + pos );
public Object getItem( int position ) { return m_items[position]; }
@Override
public View getView( final int position, View convertView,
ViewGroup parent )
{
final InviterItem item = m_items[position];
final LinearLayout layout = (LinearLayout)
inflate( R.layout.inviter_item_frame );
CheckBox box = (CheckBox)layout.findViewById( R.id.inviter_check );
// Give subclass a chance to install and populate its view
FrameLayout frame = (FrameLayout)layout.findViewById( R.id.frame );
View child = inflate( m_itemId );
frame.addView( child );
onChildAdded( child, m_items[position] );
m_counts.put( item, 1 );
if ( XWPrefs.getCanInviteMulti( m_activity ) && 1 < m_nMissing ) {
Spinner spinner = (Spinner)
layout.findViewById(R.id.nperdev_spinner);
ArrayAdapter<String> adapter =
new ArrayAdapter<String>( m_activity, android.R.layout
.simple_spinner_item );
for ( int ii = 1; ii <= m_nMissing; ++ii ) {
String str = getQuantityString( R.plurals.nplayers_fmt, ii, ii );
adapter.add( str );
}
spinner.setAdapter( adapter );
spinner.setVisibility( View.VISIBLE );
spinner.setOnItemSelectedListener( new OnItemSelectedListener() {
public void onItemSelected( AdapterView<?> parent,
View view, int pos,
long id )
{
m_counts.put( item, 1 + pos );
tryEnable();
}
public void onNothingSelected( AdapterView<?> parent ) {}
} );
}
CompoundButton.OnCheckedChangeListener listener =
new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged( CompoundButton buttonView,
boolean isChecked ) {
if ( !isChecked ) {
m_setChecked = false;
}
if ( isChecked ) {
m_checked.add( item );
} else {
m_checked.remove( item );
// // User's now making changes; don't check new views
// m_setChecked = false;
}
onItemChecked( item, isChecked );
tryEnable(); tryEnable();
} }
};
box.setOnCheckedChangeListener( listener );
if ( m_setChecked || m_checked.contains( item ) ) { public void onNothingSelected( AdapterView<?> parent ) {}
box.setChecked( true ); } );
} else if ( null != m_lastDev && m_lastDev.equals(item.getDev()) ) {
m_lastDev = null;
box.setChecked( true );
}
return layout;
} }
public String getAddr( CheckBox box ) { return (String)box.getTag(); } box.setOnCheckedChangeListener( new OnCheckedChangeListener() {
public String getName( CheckBox box ) { return box.getText().toString(); } @Override
} public void onCheckedChanged( CompoundButton buttonView,
boolean isChecked ) {
if ( !isChecked ) {
m_setChecked = false;
}
if ( isChecked ) {
m_checked.add( item );
} else {
m_checked.remove( item );
}
onItemChecked( item, isChecked );
tryEnable();
}
} );
if ( m_setChecked || m_checked.contains( item ) ) {
box.setChecked( true );
} else if ( null != m_lastDev && m_lastDev.equals(item.getDev()) ) {
m_lastDev = null;
box.setChecked( true );
}
return layout;
}
} }

View file

@ -463,7 +463,7 @@ public class RelayInviteDelegate extends InviteDelegate {
}); });
addSelf(); addSelf();
updateListAdapter( m_devIDRecs ); updateList( m_devIDRecs );
tryEnable(); tryEnable();
} }

View file

@ -302,7 +302,7 @@ public class SMSInviteDelegate extends InviteDelegate {
} }
}); });
updateListAdapter( m_phoneRecs ); updateList( m_phoneRecs );
tryEnable(); tryEnable();
} }

View file

@ -129,6 +129,6 @@ public class WiDirInviteDelegate extends InviteDelegate
// names[ii] = m_macsToName.get(mac); // names[ii] = m_macsToName.get(mac);
} }
updateListAdapter( pairs ); updateList( pairs );
} }
} }

View file

@ -28,6 +28,7 @@ import android.widget.ListAdapter;
*/ */
public abstract class XWListAdapter extends BaseAdapter public abstract class XWListAdapter extends BaseAdapter
implements ListAdapter { implements ListAdapter {
private static final String TAG = XWListAdapter.class.getSimpleName();
private int m_count; private int m_count;
public XWListAdapter() { public XWListAdapter() {

View file

@ -1,72 +1,77 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView android:id="@+id/invite_desc"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:padding="8dp"
/>
<TextView android:id="@+id/invite_extra"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:padding="8dp"
android:visibility="gone"
/>
<ListView android:id="@id/android:list"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:drawSelectorOnTop="false" android:orientation="vertical"
android:layout_weight="1" >
android:padding="8dp" <LinearLayout android:orientation="vertical"
/> android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView android:id="@android:id/empty" <TextView android:id="@+id/invite_desc"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:padding="8dp"
/>
<TextView android:id="@+id/invite_extra"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:padding="8dp"
android:visibility="gone"
/>
<LinearLayout android:orientation="vertical"
android:id="@+id/invitees"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="8dp"
/>
<TextView android:id="@+id/empty"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
/>
<LinearLayout android:id="@+id/progress_line"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:padding="5dp"
>
<TextView android:id="@+id/progress_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:layout_gravity="center_horizontal"
/>
<ProgressBar android:id="@+id/progress"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:min="0"
/>
</LinearLayout>
<Button android:id="@+id/button_invite"
android:text="@string/button_invite"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="20dp"
/> />
<LinearLayout android:id="@+id/progress_line" <FrameLayout android:id="@+id/button_bar"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:padding="5dp"
>
<TextView android:id="@+id/progress_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:layout_gravity="center_horizontal"
/>
<ProgressBar android:id="@+id/progress"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:min="0"
/> />
</LinearLayout> </LinearLayout>
</ScrollView>
<Button android:id="@+id/button_invite"
android:text="@string/button_invite"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<FrameLayout android:id="@+id/button_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>