-android: multiple layout improvements

This commit is contained in:
Joachim Fritzsch 2013-04-06 16:19:44 +02:00
parent 96f3bdf16b
commit e16f4d3c1f
23 changed files with 196 additions and 122 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -22,28 +22,11 @@
android:layout_height="wrap_content"
android:padding="10dip"
android:orientation="vertical">
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance.Medium" >
</TextView>
<EditText
android:id="@+id/Input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:layout_marginTop="20dip">
android:inputType="numberDecimal">
<requestFocus />
</EditText>
<Button
android:id="@+id/buttonPrefSubmit"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dip"
android:text="@string/prefs_submit_button" />
</LinearLayout>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is part of BOINC.
http://boinc.berkeley.edu
Copyright (C) 2012 University of California
BOINC is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
BOINC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with BOINC. If not, see <http://www.gnu.org/licenses/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dip"
android:orientation="vertical">
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100">
</SeekBar>
<TextView
android:id="@+id/seekbar_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" >
</TextView>
</LinearLayout>

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/projects_add"
android:enabled="true"
android:visible="true"
android:title="@string/projects_add"
android:icon="@drawable/ic_menu_add"></item>
android:icon="@drawable/plusw"></item>
</menu>

View File

@ -28,4 +28,7 @@
<color name="active">#11A800</color>
<color name="paused">#FCEC3D</color>
<color name="error">#ED0202</color>
<color name="black">#000000</color>
</resources>

View File

@ -120,12 +120,12 @@
<string name="tab_debug">Debug</string>
<!-- status tab strings -->
<string name="status_running">Calculating&#8230;</string>
<string name="status_running_long">Thank you!</string>
<string name="status_running">Thanks!</string>
<string name="status_running_long">Calculating tasks&#8230;</string>
<string name="status_paused">Paused</string>
<string name="status_paused_long">Computation suspended.</string>
<string name="status_idle">Idle</string>
<string name="status_idle_long">Nothing to do right now.</string>
<string name="status_idle_long">Waiting for tasks&#8230;</string>
<string name="status_computing_disabled">Stopped</string>
<string name="status_computing_disabled_long">Tap to continue!</string>
<string name="disable_computation">Disable computation</string>
@ -134,7 +134,8 @@
<!-- preferences tab strings -->
<string name="prefs_loading">Reading preferences&#8230;</string>
<string name="prefs_submit_button">OK</string>
<string name="prefs_submit_button">Save</string>
<string name="prefs_cancel_button">Cancel</string>
<string name="prefs_dialog_title">Please enter desired value for: </string>
<string name="prefs_category_general">General</string>
<string name="prefs_category_network">Network</string>
@ -230,7 +231,7 @@
<!-- suspend reasons -->
<string name="suspend_unknown">Computation paused.</string>
<string name="suspend_idle">No BOINC tasks ready for computation.</string>
<string name="suspend_batteries">Not connected to power source.</string>
<string name="suspend_batteries">Not connected to charger.</string>
<string name="suspend_useractive">User is active.</string>
<string name="suspend_userreq">Stopped manually.</string>
<string name="suspend_tod">Out of computation time-frame.</string>
@ -245,7 +246,7 @@
<string name="suspend_os">Stopped by Android.</string>
<string name="suspend_wifi">Can\'t fetch work, no WiFi connection!</string>
<string name="suspend_battery_charging">Your device\'s battery is charging.</string>
<string name="suspend_battery_overheating">Your device\'s battery is overheating.</string>
<string name="suspend_battery_overheating">Your device\'s battery needs to cool down.</string>
<!-- rpc reasons -->
<string name="rpcreason_userreq">Requested by user</string>

View File

@ -29,9 +29,13 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
@ -278,4 +282,39 @@ public class BOINCActivity extends TabActivity {
Log.d(TAG, "finishing application, good bye!");
super.finish();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
Log.d(TAG, "onCreateOptionsMenu()");
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.status_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d(TAG, "onOptionsItemSelected()");
switch (item.getItemId()) {
case R.id.exit_boinc:
Log.d(TAG,"exit BOINC");
new QuitClientAsync().execute();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
// monitor.quitClient is blocking (Thread.sleep)
// execute in AsyncTask to maintain UI responsiveness
private final class QuitClientAsync extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
monitor.quitClient();
return null;
}
}
}

View File

@ -146,6 +146,9 @@ public class EventLogActivity extends FragmentActivity {
public boolean onCreateOptionsMenu(Menu menu) {
Log.d(TAG, "onCreateOptionsMenu()");
// call BOINCActivity's onCreateOptionsMenu to combine both menus
getParent().onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.eventlog_menu, menu);
@ -161,7 +164,7 @@ public class EventLogActivity extends FragmentActivity {
onEmailTo();
return true;
default:
return super.onOptionsItemSelected(item);
return getParent().onOptionsItemSelected(item);
}
}

View File

@ -26,25 +26,27 @@ import edu.berkeley.boinc.adapter.PrefsListItemWrapperBool;
import edu.berkeley.boinc.adapter.PrefsListItemWrapperDouble;
import edu.berkeley.boinc.client.Monitor;
import edu.berkeley.boinc.rpc.GlobalPreferences;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
public class PrefsActivity extends Activity implements OnClickListener {
public class PrefsActivity extends FragmentActivity {
private final String TAG = "BOINC PrefsActivity";
@ -59,6 +61,7 @@ public class PrefsActivity extends Activity implements OnClickListener {
private AppPreferences appPrefs = null; //Android specific preferences, singleton of monitor
private Dialog dialog; //Dialog for input on non-Bool preferences
private PrefsListItemWrapperDouble dialogItem; // saves content of preference Dialog is showing
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -155,9 +158,7 @@ public class PrefsActivity extends Activity implements OnClickListener {
loadingHeader.setText(R.string.prefs_loading);
}
/*
* Gets triggered by change of checkboxes. (Boolean prefs)
*/
// onClick of listview items with PrefsListItemBool
public void onCbClick (View view) {
Log.d(TAG,"onCbClick");
Integer ID = (Integer) view.getTag();
@ -185,27 +186,60 @@ public class PrefsActivity extends Activity implements OnClickListener {
}
}
// onClick of listview items with PrefsListItemWrapperDouble
public void onItemClick (View view) {
Integer ID = (Integer) view.getTag();
Log.d(TAG,"onItemClick " + ID);
showDialog(ID);
}
/*
* Gets called when showDialog is triggered
*/
@Override
protected Dialog onCreateDialog(int id) {
dialog = new Dialog(this); //instance new dialog
dialog.setContentView(R.layout.prefs_layout_dialog);
Button button = (Button) dialog.findViewById(R.id.buttonPrefSubmit);
button.setOnClickListener(this);
//EditText edit = (EditText) dialog.findViewById(R.id.Input);
TextView description = (TextView) dialog.findViewById(R.id.description);
description.setText(id);
dialog.setTitle(R.string.prefs_dialog_title);
button.setId(id); //set input id, for evaluation in onClick
return dialog;
PrefsListItemWrapperDouble listItem = (PrefsListItemWrapperDouble) view.getTag();
Log.d(TAG,"onItemClick " + listItem.ID);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
final View dialogContent;
if(listItem.isPct) {
dialogContent = inflater.inflate(R.layout.prefs_layout_dialog_pct, null);
TextView sliderProgress = (TextView) dialogContent.findViewById(R.id.seekbar_status);
sliderProgress.setText(listItem.status.intValue() + " %");
SeekBar slider = (SeekBar) dialogContent.findViewById(R.id.seekbar);
slider.setProgress(listItem.status.intValue());
slider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){
String progressString = progress + " %";
TextView sliderProgress = (TextView) dialogContent.findViewById(R.id.seekbar_status);
sliderProgress.setText(progressString);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});
} else {
dialogContent = inflater.inflate(R.layout.prefs_layout_dialog, null);
}
builder.setMessage(listItem.ID)
.setView(dialogContent)
.setNegativeButton(R.string.prefs_cancel_button, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogI, int id) {
dialog.cancel();
}
})
.setPositiveButton(R.string.prefs_submit_button, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogI, int id) {
double value;
if(dialogItem.isPct) {
SeekBar slider = (SeekBar) dialog.findViewById(R.id.seekbar);
value = slider.getProgress();
} else {
EditText edit = (EditText) dialog.findViewById(R.id.Input);
String input = edit.getText().toString();
Double valueTmp = parseInputValueToDouble(input);
if(valueTmp == null) return;
value = valueTmp;
}
writeDoublePreference(dialogItem.ID, value);
}
});
dialog = builder.create();
dialog.show();
dialogItem = listItem; // set dialog content
}
@Override
@ -214,31 +248,8 @@ public class PrefsActivity extends Activity implements OnClickListener {
super.onDestroy();
doUnbindService();
}
/*
* Gets called when Dialog's confirm button is clicked
*/
@Override
public void onClick(View v) {
Log.d(TAG,"dialogs confirm button clicked");
Button button = (Button) v;
Integer id = button.getId();
EditText input = (EditText) dialog.findViewById(R.id.Input);
// parse value
Double value = 0.0;
try {
String tmp = input.getText().toString();
tmp=tmp.replaceAll(",","."); //replace e.g. European decimal seperator "," by "."
value = Double.parseDouble(tmp);
Log.d(TAG,"onClick with input value " + value);
} catch (Exception e) {
Log.w(TAG, e);
Toast toast = Toast.makeText(getApplicationContext(), "wrong format!", Toast.LENGTH_SHORT);
toast.show();
return;
}
private void writeDoublePreference(int id, double value) {
// update preferences
switch (id) {
case R.string.prefs_disk_max_pct_header:
@ -276,6 +287,22 @@ public class PrefsActivity extends Activity implements OnClickListener {
dialog.dismiss();
new WriteClientPrefsAsync().execute(clientPrefs);
}
public Double parseInputValueToDouble(String input) {
// parse value
Double value = 0.0;
try {
input=input.replaceAll(",","."); //replace e.g. European decimal seperator "," by "."
value = Double.parseDouble(input);
Log.d(TAG,"parseInputValueToDouble: " + value);
return value;
} catch (Exception e) {
Log.w(TAG, e);
Toast toast = Toast.makeText(getApplicationContext(), "wrong format!", Toast.LENGTH_SHORT);
toast.show();
return null;
}
}
private final class WriteClientPrefsAsync extends AsyncTask<GlobalPreferences,Void,Boolean> {

View File

@ -174,6 +174,9 @@ public class ProjectsActivity extends FragmentActivity {
public boolean onCreateOptionsMenu(Menu menu) {
Log.d(TAG, "onCreateOptionsMenu()");
// call BOINCActivity's onCreateOptionsMenu to combine both menus
getParent().onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.projects_menu, menu);
@ -189,7 +192,7 @@ public class ProjectsActivity extends FragmentActivity {
onProjectAdd();
return true;
default:
return super.onOptionsItemSelected(item);
return getParent().onOptionsItemSelected(item); // if item id can not be mapped, call parents method
}
}

View File

@ -28,13 +28,9 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
@ -155,6 +151,8 @@ public class StatusActivity extends Activity {
switch(status.computingSuspendReason) {
case BOINCDefs.SUSPEND_REASON_BATTERIES:
statusDescriptor.setText(R.string.suspend_batteries);
statusImage.setImageResource(R.drawable.notconnectedw48);
statusHeader.setVisibility(View.GONE);
break;
case BOINCDefs.SUSPEND_REASON_USER_ACTIVE:
statusDescriptor.setText(R.string.suspend_useractive);
@ -167,6 +165,8 @@ public class StatusActivity extends Activity {
break;
case BOINCDefs.SUSPEND_REASON_BENCHMARKS:
statusDescriptor.setText(R.string.suspend_bm);
statusImage.setImageResource(R.drawable.watchw48);
statusHeader.setVisibility(View.GONE);
break;
case BOINCDefs.SUSPEND_REASON_DISK_SIZE:
statusDescriptor.setText(R.string.suspend_disksize);
@ -197,9 +197,13 @@ public class StatusActivity extends Activity {
break;
case BOINCDefs.SUSPEND_REASON_BATTERY_CHARGING:
statusDescriptor.setText(R.string.suspend_battery_charging);
statusImage.setImageResource(R.drawable.batteryw48);
statusHeader.setVisibility(View.GONE);
break;
case BOINCDefs.SUSPEND_REASON_BATTERY_OVERHEATED:
statusDescriptor.setText(R.string.suspend_battery_overheating);
statusImage.setImageResource(R.drawable.batteryw48);
statusHeader.setVisibility(View.GONE);
break;
default:
statusDescriptor.setText(R.string.suspend_unknown);
@ -227,8 +231,8 @@ public class StatusActivity extends Activity {
}
break;
case ClientStatus.COMPUTING_STATUS_COMPUTING:
statusHeader.setText(R.string.status_running);
statusImage.setImageResource(R.drawable.playw48);
statusHeader.setVisibility(View.GONE);
statusImage.setImageResource(R.drawable.cogsw48);
statusImage.setContentDescription(getString(R.string.status_running));
statusDescriptor.setText(R.string.status_running_long);
changeRunmodeImage.setImageResource(R.drawable.stopw24);
@ -256,39 +260,4 @@ public class StatusActivity extends Activity {
}
} catch (Exception e) {Log.e(TAG, "could not map status tag", e);}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
Log.d(TAG, "onCreateOptionsMenu()");
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.status_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d(TAG, "onOptionsItemSelected()");
switch (item.getItemId()) {
case R.id.exit_boinc:
Log.d(TAG,"exit BOINC");
new QuitClientAsync().execute();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
// monitor.quitClient is blocking (Thread.sleep)
// execute in AsyncTask to maintain UI responsiveness
private final class QuitClientAsync extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
monitor.quitClient();
return null;
}
}
}

View File

@ -71,7 +71,7 @@ public class PrefsListAdapter extends ArrayAdapter<PrefsListItemWrapper>{
}
} else if(listItem instanceof PrefsListItemWrapperDouble) {
v = vi.inflate(R.layout.prefs_layout_listitem, null);
v.setTag(listItem.ID); //set ID as tag to view, since root layout defines onClick method
v.setTag(listItem); //set listItem as tag to view, since root layout defines onClick method
TextView header = (TextView) v.findViewById(R.id.header);
header.setText(((PrefsListItemWrapperDouble) listItem).header);
TextView status = (TextView) v.findViewById(R.id.status);

View File

@ -28,6 +28,7 @@ public class PrefsListItemWrapperDouble extends PrefsListItemWrapper {
public String header = "";
public Double status;
public Boolean isPct; // shows whether value is percentage, therefore using a SeekBar
public PrefsListItemWrapperDouble(Context ctx, Integer ID, Integer categoryID, Double status) {
super(ctx, ID, categoryID);
@ -39,27 +40,35 @@ public class PrefsListItemWrapperDouble extends PrefsListItemWrapper {
switch (id) {
case R.string.prefs_disk_max_pct_header:
header = ctx.getString(R.string.prefs_disk_max_pct_header);
isPct = true;
break;
case R.string.prefs_disk_min_free_gb_header:
header = ctx.getString(R.string.prefs_disk_min_free_gb_header);
isPct = false;
break;
case R.string.prefs_network_daily_xfer_limit_mb_header:
header = ctx.getString(R.string.prefs_network_daily_xfer_limit_mb_header);
isPct = false;
break;
case R.string.prefs_cpu_number_cpus_header:
header = ctx.getString(R.string.prefs_cpu_number_cpus_header);
isPct = true;
break;
case R.string.prefs_cpu_other_load_suspension_header:
header = ctx.getString(R.string.prefs_cpu_other_load_suspension_header);
isPct = true;
break;
case R.string.prefs_cpu_time_max_header:
header = ctx.getString(R.string.prefs_cpu_time_max_header);
isPct = true;
break;
case R.string.prefs_memory_max_busy_header:
header = ctx.getString(R.string.prefs_memory_max_busy_header);
isPct = true;
break;
case R.string.prefs_memory_max_idle_header:
header = ctx.getString(R.string.prefs_memory_max_idle_header);
isPct = true;
break;
default:
Log.d(TAG, "map failed!");