Can any body explain this code from Hello Android book - android

I cannot understand this code in page number 68-69 in Hello Android book. Some methods used in the code are new to me. Can anybody elaborate and explain the code.
private static final String TAG = "Sudoku" ;
private void openNewGameDialog() {
new AlertDialog.Builder(this)
.setTitle(R.string.new_game_title)
.setItems(R.array.difficulty, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface,int i) {
startGame(i);
}
})
.show();
}
private void startGame(int i) {
Log.d(TAG, "clicked on " + i);
// Start game here...
}

All it does is when you call openNewGameDialog() it will create an alertdialog with an assigned title and list of options from a resource file ("R.array.difficulty" is an integer value ultimately pointing to a string-array declared in the file /res/values/arrays.xml). An AlertDialog is a simple to create way of getting input from the user. It can also be used for output, but many prefer Toast for that task. The
.show() at the end of it brings the dialog to the foreground.
When the items are added in that call they are assigned an onClick listener which when an item is clicked it sends the index of that item to startGame. In that function it only sends a message including the index to the logcat debug system.

Related

How do I style text in Android Java when it originates in strings.xml?

I'm trying to put a multi-paragraph message in an AlertDialog and have blank lines between the three (short) paragraphs. It works great when the string is written in my Java code but fails miserably when the string originates in strings.xml. What do I have to do differently when the text comes from strings.xml?
Please note that the value of message999 in my strings.xml is exactly what is in the commented-out message variable in my Java code.
Here's my code.
private void displayEmptySetMessage() {
Toast.makeText(this, getString(R.string.message999), Toast.LENGTH_LONG).show();
AlertDialog.Builder builder = new AlertDialog.Builder(ListSales.this);
//Set the message.
//String message = "<p>There are currently no sales in the table.</p><br><p>If this is normal - you may have deleted all of your sales - and you wish to add rows with the add feature, please press Proceed.</p><br><p>If you think something is wrong, press Exit and contact your system administrator.</p>";
String message = getString(R.string.message999);
CharSequence styledMessage = Html.fromHtml(message, Html.TO_HTML_PARAGRAPH_LINES_INDIVIDUAL);
builder.setMessage(styledMessage);
//Set the title.
builder.setTitle("No Sales");
//Add the buttons
builder.setNegativeButton(R.string.proceed, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User clicked Proceed button - do nothing except dismiss the dialog
}
});
builder.setPositiveButton(R.string.exit, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//User clicked Exit button - notify the system administrator and exit the app
Toast.makeText(ListSales.this, R.string.message009, Toast.LENGTH_LONG).show(); //placeholder
java.lang.System.exit(0);
}
});
//Create and display the AlertDialog
AlertDialog dialog = builder.create();
dialog.show();
}
If the commented out string is sufficient for what you want, there are a couple of easy ways you could generate it (without html formatting).
You could include newline characters in the strings.xml file, as in
<string name="mymessage">This is paragraph 1.\n\n\nThis is paragraph 2.\n\n\nThis is the last paragraph.</string>
or you could separate the paragraphs in the XML file
<string name="message_par1">This is paragraph 1.</string>
<string name="message_par2">This is paragraph 1.</string>
<string name="message_par3">This is the last paragraph.</string>
and assemble the full message in your code
String message = getString(R.string.message_par1) + "\n\n\n" +
getString(R.string.message_par2) + "\n\n\n" +
getString(R.string.message_par3);
builder.setMessage(message);
This doesn't let you do any html formatting, but if you were just trying to mimic the string you had commented out this should work.
Maybe you can create the message like this.
String message = "Paragraph1" + "\n\n\n" +
"Paragraph 2" + "\n\n\n" +
"Paragraph 3"
builder.setMessage(message);

Checkbox status not being passed when dialog button pressed

I'm trying to implement a check box in a MaterialDialog using this library, and the check box asks the user if they don't want to see that dialog again. The dialog appears if the user's phone has NFC, but it is deactivated.
If the user presses the positive button in the dialog and has the box ticked, then it accesses a Realm object with a Boolean attribute named "NfcStatus", and sets that to true. If they press the negative button with the box ticked, then that Realm object's NfcStatus is set to false.
Here's the code of the MaterialDialog:
new MaterialDialog.Builder(context)
.title("NFC")
.content("NFC is disabled. Would you like to activate it?")
.items(R.array.checkbox) //this just has one string in it which says "Please don't show me this again"
.itemsCallbackMultiChoice(null, new MaterialDialog.ListCallbackMultiChoice() {
#Override
public boolean onSelection(MaterialDialog dialog, Integer[] which, CharSequence[] text) {
/**
* If you use alwaysCallMultiChoiceCallback(), which is discussed below,
* returning false here won't allow the newly selected check box to actually be selected.
* See the limited multi choice dialog example in the sample project for details.
**/
checkboxIsChecked = true; //TODO: checkboxIsChecked isn't being passed into onPositive or onNegative
return true;
}
})
.positiveText(R.string.accept)
.positiveColorRes(R.color.main_theme_color)
.negativeText(R.string.decline)
.negativeColorRes(R.color.main_theme_color)
.callback(new MaterialDialog.ButtonCallback() {
#Override
public void onPositive(MaterialDialog dialog) {
//this was how I was checking if checkboxIsChecked was true or false
Log.d("checkboxIsChecked", checkboxIsChecked?"true":"false"); }
if (checkboxIsChecked) {begins
if (ks.contains(KEY_NAME)) {
realmKey = ks.get(KEY_NAME);
}
realm = Realm.getInstance(context, realmKey);
RealmPhone realmPhone = realm.where(RealmPhone.class).findFirst(); realmPhone.setNfcStatus(true);
}
activity.finish();
startNfcSettingsActivity();
Toast.makeText(context, R.string.nfc_disabled_message, Toast.LENGTH_LONG).show();
}
#Override
public void onNegative(MaterialDialog dialog) {
if (checkboxIsChecked) {
if (ks.contains(KEY_NAME)) {
realmKey = ks.get(KEY_NAME);
}
realm = Realm.getInstance(context, realmKey);
RealmPhone realmPhone = realm.where(RealmPhone.class).findFirst();
realmPhone.setNfcStatus(false);
}
}
})
.cancelable(false)
.show();
The problem was that even if the check box was ticked, the checkboxIsChecked variable was still false when using it in onPositive or onNegative, so it was never being written to the Realm object. Am I doing this the wrong way?
For changing and saving the RealmObject, you need to use transactions. Related documents can be found here.
In you case, it would be something like:
realm = Realm.getInstance(context, realmKey);
// I'm not quite sure how did you create the realmPhone at the first time,
// just assume you have one realmPhone in the Realm.
RealmPhone realmPhone = realm.where(RealmPhone.class).findFirst();
realm.beginTransaction();
realmPhone.setNfcStatus(false);
realm.commitTransaction();
// Close the realm instance after using it is very important! To avoid leaks.
realm.close();
BTW, it seems code:
RealmPhone realmPhone = realm.where(RealmPhone.class).findFirst();
realmPhone.setNfcStatus(false);
is not called. If it does, a IllegalStateException should be thrown since you didn't call it in a Realm transaction. Or maybe RealmPhone is not inherited from RealmObject?

Why arent my log messages showing up?

I have some code that build a dialog box and makes a listener for it. The dialog box displays fine, but the code inside the listener doesn't seem to run, and I don't know why.
private void showBackgrounDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(MeacruxActivity.this);
builder.setTitle(R.string.background_dialog_title).setCancelable(true)
.setItems(R.array.background_options,
new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int selection) {
Log.d(logID, "the selection is: " + selection);
if(backgrounds.length==selection){
notImplementedYet.show();
return;
}
setBckground(backgrounds[selection]);
}
});
currentDialog = builder.create();
currentDialog.show();
}
private void setBackground(String bgName) {
Log.d(logID, bgName);
}
The dialog shows up properly with all the options and everything, but when I click on one nothing come sup in the log.... Why is that?
Edit: I did some more testing and I can confirm that the code inside of the onClick function is being run, its just that the log isnt showing up...
I'm assuming you are looking in eclipse or studio
In DDMS view, make sure the device is selected.
In Logcat view, make sure there's not a filter applied.
On terminal, type adb logcat... does it show up there?

AlertDialog with a Cursor

I am looking for some help in understanding the workings of the Alert Dialog. I currently have a working dialog that retrieves a listing of players from the SQLite database. The idea is for the user to select a listed player from the list and I store that name in a variable. The snipet of code below gives me the position integer of the name.
return new AlertDialog.Builder(this)
.setCancelable(false)
.setTitle("Choose a Player")
.setSingleChoiceItems(dba.getAllPlayers(), -1, Constants.playerName, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
***** get the name of the player selected ****
dialog.dismiss();
startMenu();
}
})
.create();
I need the syntax to reference a cursor. I understand the more basic listing of an array and referencing the selected item from that array (items[item]) as per the doco (http://developer.android.com/guide/topics/ui/dialogs.html), but how do I reference the listing from my call to the database?
Tried playerName = dba.getAllPlayers().getString(item); but I get a "CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1" type error.
Thanks in advance and hope someone might shed some light on this for me. Cheers.
Glenn
Aging Cobol Programmer
Very New to Android
If your do:
playerName = dba.getAllPlayers().getString(item);
You are telling android to search the string in the column number item from the Cursor. This of course makes no sense at all. What you need is to ask for the position, thus this looks better:
final Cursor cursor = dba.getAllPlayers()
.setSingleChoiceItems(cursor, -1, Constants.playerName, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
cursor.moveToPosition(item);
String blah = cursor.getString(cursor.getColumnIndex(Constants.playerName));

validate the edittext field inside alertdialog

I am using this function to insert into the database. I'd like to validate inputs from two edittext fields. Whenever I push ok button without giving any inputs, the program crashes.I tried to print the values as well, but it didnt display in logcat.Am i doing anything wrong?
private void add() {
LayoutInflater inflater=LayoutInflater.from(this);
final View addView=inflater.inflate(R.layout.add_country, null);
new AlertDialog.Builder(this)
.setTitle("Add new country/year")
.setView(addView)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClickDialogInterface dialog,int whichButton) {
/* Read alert input */
EditText editCountry =(EditText)addView.findViewById(R.id.editCountry);
String country = editCountry.getText().toString();
EditText editYear =(EditText)addView.findViewById(R.id.editYear);
int year = Integer.parseInt( editYear.getText().toString() );
if(editCountry.getText().toString().trim().length()>0 && editYear.getText().toString().trim().length()>0){
/* Open DB and add new entry */
db.open();
db.insertEntry(country,year);
/* Create new cursor to update list. Must be possible to handle
* in a better way. */
entryCursor = db.fetchAllEntries(); // all country/year pairs
adapter = new SimpleCursorAdapter(CountryEditor.this,
R.layout.country_row,entryCursor,
new String[] {"country", "year"},
new int[] {R.id.country, R.id.year});
setListAdapter(adapter);
db.close();
}
else{
Toast.makeText(CountryEditor.this,
"You need to enter Country AND Year.", Toast.LENGTH_LONG).show();
}
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int whichButton) {
// ignore, just dismiss
}
})
.show();
}
You are calling editBlah.getText().toString() which can return "";
When parsing this to an integer an Exception will be thrown.
( It could also be, if you call .getText() on a view which has initialised to null (ie, you have incorrectly specified the id for the ID you want) a NullPointerException will be thrown. Without the Stacktrace you wouldn't be able to tell which - try and post your stack trace with the question where possible ).
You're question is correct - What you need to do is validate the input you're getting: ie:
int year = Integer.parseInt( editYear.getText().toString() );
should be:
if(editYear.getText().toString().equalsIgnoreCase("")) {
// Cannot parse into an int therefore perform some action which will notify the
// user they haven't entered the correct value.
}
Or even the following if you are already going to be validating your int values:
int year = Integer.parseInt( editYear.getText().toString().equalsIgnoreCase("") ?
"-1" : editYear.getText().toString());
editCountry.getText() equals with nullstring? nullponterexception

Categories

Resources