fix problems tracking what's checked by keeping separate array of

booleans -- since list items come and go as you scroll.  Means moving
some behavior out of InviteActivity superclass, and that untested BT
subclass may have new bugs.
This commit is contained in:
Eric House 2012-04-05 07:47:59 -07:00
parent 784a5d5d44
commit bffc403c0c
4 changed files with 119 additions and 52 deletions

View file

@ -39,9 +39,11 @@ import android.os.Handler;
import junit.framework.Assert; import junit.framework.Assert;
public class BTInviteActivity extends InviteActivity { public class BTInviteActivity extends InviteActivity
implements CompoundButton.OnCheckedChangeListener {
private boolean m_firstScan; private boolean m_firstScan;
private int m_checkCount;
@Override @Override
protected void onCreate( Bundle savedInstanceState ) protected void onCreate( Bundle savedInstanceState )
@ -50,7 +52,7 @@ public class BTInviteActivity extends InviteActivity {
R.id.button_invite, R.id.button_rescan, R.id.button_invite, R.id.button_rescan,
R.id.button_clear, R.id.invite_desc, R.id.button_clear, R.id.invite_desc,
R.string.invite_bt_descf ); R.string.invite_bt_descf );
tryEnable();
m_firstScan = true; m_firstScan = true;
BTService.clearDevices( this, null ); // will return names BTService.clearDevices( this, null ); // will return names
} }
@ -117,6 +119,25 @@ public class BTInviteActivity extends InviteActivity {
return result; return result;
} }
protected void tryEnable()
{
m_okButton.setEnabled( m_checkCount == m_nMissing );
m_clearButton.setEnabled( 0 < m_checkCount );
}
public void onCheckedChanged( CompoundButton buttonView,
boolean isChecked )
{
if ( isChecked ) {
++m_checkCount;
} else {
--m_checkCount;
}
DbgUtils.logf( "BTInviteActivity.onCheckedChanged( isChecked=%b ); "
+ "count now %d", isChecked, m_checkCount );
tryEnable();
}
private class BTDevsAdapter extends XWListAdapter { private class BTDevsAdapter extends XWListAdapter {
private String[] m_devs; private String[] m_devs;
public BTDevsAdapter( String[] devs ) public BTDevsAdapter( String[] devs )

View file

@ -39,8 +39,7 @@ import android.os.Handler;
import junit.framework.Assert; import junit.framework.Assert;
abstract class InviteActivity extends XWListActivity abstract class InviteActivity extends XWListActivity
implements View.OnClickListener, implements View.OnClickListener {
CompoundButton.OnCheckedChangeListener {
public static final String DEVS = "DEVS"; public static final String DEVS = "DEVS";
public static final String INTENT_KEY_NMISSING = "NMISSING"; public static final String INTENT_KEY_NMISSING = "NMISSING";
@ -49,7 +48,6 @@ abstract class InviteActivity extends XWListActivity
protected Button m_okButton; protected Button m_okButton;
protected Button m_rescanButton; protected Button m_rescanButton;
protected Button m_clearButton; protected Button m_clearButton;
protected int m_checkCount = 0;
protected void onCreate( Bundle savedInstanceState, int view_id, protected void onCreate( Bundle savedInstanceState, int view_id,
int button_invite, int button_rescan, int button_invite, int button_rescan,
@ -71,7 +69,6 @@ abstract class InviteActivity extends XWListActivity
TextView desc = (TextView)findViewById( desc_id ); TextView desc = (TextView)findViewById( desc_id );
desc.setText( Utils.format( this, desc_strf, m_nMissing ) ); desc.setText( Utils.format( this, desc_strf, m_nMissing ) );
m_checkCount = 0;
tryEnable(); tryEnable();
} }
@ -90,25 +87,7 @@ abstract class InviteActivity extends XWListActivity
} }
} }
public void onCheckedChanged( CompoundButton buttonView, abstract void tryEnable() ;
boolean isChecked )
{
DbgUtils.logf( "InviteActivity.onCheckedChanged( isChecked=%b )",
isChecked );
if ( isChecked ) {
++m_checkCount;
} else {
--m_checkCount;
}
tryEnable();
}
protected void tryEnable()
{
m_okButton.setEnabled( m_checkCount == m_nMissing );
m_clearButton.setEnabled( 0 < m_checkCount );
}
abstract String[] listSelected(); abstract String[] listSelected();
abstract void scan(); abstract void scan();
abstract void clearSelected(); abstract void clearSelected();

View file

@ -26,15 +26,17 @@ import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageButton; import android.widget.CompoundButton;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView; import android.widget.ListView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import junit.framework.Assert; import junit.framework.Assert;
import org.eehouse.android.xw4.jni.CommonPrefs; import org.eehouse.android.xw4.jni.CommonPrefs;
@ -45,6 +47,7 @@ public class SMSInviteActivity extends InviteActivity {
private ArrayList<String> m_names; private ArrayList<String> m_names;
private ArrayList<String> m_phones; private ArrayList<String> m_phones;
private ArrayList<Boolean> m_checks;
private SMSPhonesAdapter m_adapter; private SMSPhonesAdapter m_adapter;
private EditText m_manualField; private EditText m_manualField;
@ -64,8 +67,7 @@ public class SMSInviteActivity extends InviteActivity {
String number = m_manualField.getText().toString(); String number = m_manualField.getText().toString();
if ( 0 < number.length() ) { if ( 0 < number.length() ) {
m_manualField.setText(""); m_manualField.setText("");
m_phones.add( number ); add( getString( R.string.manual_owner_name ), number );
m_names.add( getString( R.string.manual_owner_name ) );
saveState(); saveState();
rebuildList(); rebuildList();
} }
@ -74,6 +76,7 @@ public class SMSInviteActivity extends InviteActivity {
getSavedState(); getSavedState();
rebuildList(); rebuildList();
tryEnable();
} }
@Override @Override
@ -90,7 +93,8 @@ public class SMSInviteActivity extends InviteActivity {
} }
} }
protected void scan() { protected void scan()
{
Intent intent = new Intent( Intent.ACTION_PICK, Intent intent = new Intent( Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI ); ContactsContract.Contacts.CONTENT_URI );
startActivityForResult( intent, GET_CONTACT ); startActivityForResult( intent, GET_CONTACT );
@ -98,33 +102,53 @@ public class SMSInviteActivity extends InviteActivity {
protected void clearSelected() protected void clearSelected()
{ {
ListView list = (ListView)findViewById( android.R.id.list ); int count = m_adapter.getCount();
int count = list.getChildCount();
for ( int ii = count - 1; ii >= 0; --ii ) { for ( int ii = count - 1; ii >= 0; --ii ) {
SMSListItem item = (SMSListItem)list.getChildAt( ii ); if ( m_checks.get( ii ) ) {
if ( item.isChecked() ) { remove( ii );
m_phones.remove( ii );
m_names.remove( ii );
} }
} }
saveState(); saveState();
rebuildList(); rebuildList();
} }
protected String[] listSelected() { protected String[] listSelected()
ListView list = (ListView)findViewById( android.R.id.list ); {
String[] result = new String[m_checkCount]; int count = m_adapter.getCount();
int count = list.getChildCount(); String[] result = new String[countChecks()];
int index = 0; int index = 0;
for ( int ii = 0; ii < count; ++ii ) { Iterator<Boolean> iter = m_checks.iterator();
SMSListItem item = (SMSListItem)list.getChildAt( ii ); for ( int ii = 0; iter.hasNext(); ++ii ) {
if ( item.isChecked() ) { if ( iter.next() ) {
result[index++] = item.getNumber(); result[index++] =
((SMSListItem)m_adapter.getItem(ii)).getNumber();
} }
} }
return result; return result;
} }
@Override
protected void tryEnable()
{
int count = countChecks();
m_okButton.setEnabled( count == m_nMissing );
m_clearButton.setEnabled( 0 < count );
}
private int countChecks()
{
int count = 0;
if ( null != m_checks ) {
Iterator<Boolean> iter = m_checks.iterator();
while ( iter.hasNext() ) {
if ( iter.next() ) {
++count;
}
}
}
return count;
}
private void addPhoneNumbers( Intent intent ) private void addPhoneNumbers( Intent intent )
{ {
Uri data = intent.getData(); Uri data = intent.getData();
@ -149,8 +173,7 @@ public class SMSInviteActivity extends InviteActivity {
// pc.getInt( pc.getColumnIndex( Phone.TYPE ) ); // pc.getInt( pc.getColumnIndex( Phone.TYPE ) );
if ( /*Phone.TYPE_MOBILE == type && */0 < number.length() ) { if ( /*Phone.TYPE_MOBILE == type && */0 < number.length() ) {
m_names.add( name ); add( name, number );
m_phones.add( number );
} }
} }
if ( len_before != m_phones.size() ) { if ( len_before != m_phones.size() ) {
@ -171,7 +194,6 @@ public class SMSInviteActivity extends InviteActivity {
{ {
m_adapter = new SMSPhonesAdapter(); m_adapter = new SMSPhonesAdapter();
setListAdapter( m_adapter ); setListAdapter( m_adapter );
m_checkCount = 0;
tryEnable(); tryEnable();
} }
@ -179,6 +201,12 @@ public class SMSInviteActivity extends InviteActivity {
{ {
m_names = CommonPrefs.getSMSNames( this ); m_names = CommonPrefs.getSMSNames( this );
m_phones = CommonPrefs.getSMSPhones( this ); m_phones = CommonPrefs.getSMSPhones( this );
int size = m_phones.size();
m_checks = new ArrayList<Boolean>(size);
for ( int ii = 0; ii < size; ++ii ) {
m_checks.add( false );
}
} }
private void saveState() private void saveState()
@ -187,6 +215,20 @@ public class SMSInviteActivity extends InviteActivity {
CommonPrefs.setSMSPhones( this, m_phones ); CommonPrefs.setSMSPhones( this, m_phones );
} }
private void add( String name, String number )
{
m_names.add( name );
m_phones.add( number );
m_checks.add( false );
}
private void remove( int index )
{
m_phones.remove( index );
m_names.remove( index );
m_checks.remove( index );
}
private class SMSPhonesAdapter extends XWListAdapter { private class SMSPhonesAdapter extends XWListAdapter {
private SMSListItem[] m_items; private SMSListItem[] m_items;
@ -196,13 +238,31 @@ public class SMSInviteActivity extends InviteActivity {
m_items = new SMSListItem[m_phones.size()]; m_items = new SMSListItem[m_phones.size()];
} }
public Object getItem( int position ) public Object getItem( final int position )
{ {
// For some reason I can't cache items to be returned.
// Checking/unchecking breaks for some but not all items,
// with some relation to whether they were scrolled into
// view. So build them anew each time (but still cache
// for by-index access.)
SMSListItem item = SMSListItem item =
(SMSListItem)Utils.inflate( SMSInviteActivity.this, (SMSListItem)Utils.inflate( SMSInviteActivity.this,
R.layout.smsinviter_item ); R.layout.smsinviter_item );
item.setOnCheckedChangeListener( SMSInviteActivity.this ); item.setChecked( m_checks.get( position ) );
item.setContents( m_names.get(position), m_phones.get(position) );
CompoundButton.OnCheckedChangeListener lstnr =
new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged( CompoundButton bv,
boolean isChecked ) {
m_checks.set( position, isChecked );
tryEnable();
}
};
item.setOnCheckedChangeListener( lstnr );
item.setContents( String.format("%d:%s", position,
m_names.get(position) ),
m_phones.get(position) );
m_items[position] = item; m_items[position] = item;
return item; return item;
} }
@ -214,7 +274,8 @@ public class SMSInviteActivity extends InviteActivity {
public boolean isChecked( int index ) public boolean isChecked( int index )
{ {
boolean checked = m_items[index].isChecked(); SMSListItem item = m_items[index];
boolean checked = null != item && item.isChecked();
return checked; return checked;
} }
} }

View file

@ -54,6 +54,12 @@ public class SMSListItem extends LinearLayout {
return tv.getText().toString(); return tv.getText().toString();
} }
public void setChecked( boolean checked )
{
CheckBox cb = (CheckBox)findViewById( R.id.checkbox );
cb.setChecked( checked );
}
public boolean isChecked() public boolean isChecked()
{ {
CheckBox cb = (CheckBox)findViewById( R.id.checkbox ); CheckBox cb = (CheckBox)findViewById( R.id.checkbox );