In my app I have a button that has a text and a variable attached to it.. for example - "inbox 20" where 20 is a variable.
Every minute I do a sync on a separate thread and get the new value of the inbox messages.
Whenever I get the new value, I do
b.setText("Inbox" + numMails); //where numMails is an int retrieved from the server.
My question is, is there any way to keep the "Inbox" part static and there forever, and just add the numMails ?
As Button's text cannot be updated partially, it's not possible.
However I assume that you want to achieve this just because of not to rewrite "Inbox " + part.
So you can achieve this by extracting a method like this:
private void setInboxButtonText(int numMails) {
StringBuilder sb = new StringBuilder();
sb.append("Inbox ");
sb.append(String.valueOf(numMails));
b.setText(sb.toString());
}
and use this method wherever you update that Button's text.
Furthermore, if you are looking for more abstract structure then I suggest you to extend android.widget.Button class like this:
public class InboxButton extends Button {
#Override
public void setText(int numMails) {
StringBuilder sb = new StringBuilder();
sb.append("Inbox ");
sb.append(String.valueOf(numMails));
super.setText(sb.toString());
}
}
and use this class while defining your Inbox Button.
You can do this way:
b.setText(b.getText().split(" ")[0] + " " + numMails);
Related
I am just getting started with RxJava/RxAndroid and I was wondering if I can use it to solve the following problem. Basically, given a Field, say a textview, and a value, a string, I am looking for a way to automatically update the textview whenever the value of the string changes. I am not sure exactly how I would implement this as an Observable. Let me demonstrate;
String str = "Test"; //the string value
TextView textView = (TextView) findViewById(R.id.textView); //the textview
Observable o = //looking for this part. Want to observe the String str
o.subscribe(new Observer<String>() { //subscribe here looking for string changes
#Override
public void onCompleted() {
System.out.println("Completed");
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(String s) {
textView.setText(s); //update the textview here
}
});
//here is where the string changes, it could be hardcoded, user input, or
//anything else really, I just want the textview to be updated automatically
//without another setText
str = "Different String";
Is what I am looking for possible with RxAndroid/RxJava?
The easiest way to accomplish that would be to use any kind of of Subject, maybe either a BehaviorSubject or a PublishSubject. A Subject is both a Subscriber (so you can put values into it with onNext) and an Observable (so you can subscribe to it). Look here for an explanation of the differences: http://reactivex.io/documentation/subject.html
So, instead of
String str = "Test";
you would have
BehaviorSubject<String> stringSubject = BehaviorSubject.<String>create("Test");
You can then directly subscribe to stringObservable.
And instead of assigning a new value to your variable like this:
str = "Hello World!";
you would do
stringSubject.onNext("Hello World!");
Oh, and never leave onError empty - doing so will quietly swallow any exceptions that may have occured earlier, and you will sit and wonder why nothing is happening. At least write e.printStacktrace().
I'm build the Fun Facts app on the Android Development Track. I decided to take a exploratory detour and try to create a very basic introductory message to the user. I changed the factTextView text to "You can click the button below to see a new fact!" and changed the showFactButton text to "Try it out!"
From there, I changed the final line onClick object (is that an object?) to the following:
public void onClick(View view) {
String fact = mFactBook.getFact();
// Update the label with our dynamic fact
factLabel.setText(fact);
// Set button text to new fact prompt
showFactButton.setText("Show another fun fact.");
This seems to work fine. However, I feel like "updating" the button text to the same new string on every press isn't always the best practice, even if it is easy and readable. I tried to add a boolean that will check the text of the button, and update it only if it has not already been updated. This is what I've come up with so far:
View.OnClickListener listener = new View.OnClickListener() {
#Override
public String launchText = getResources().getString(R.string.start_text);
public String nextText = getResources().getString(R.string.next_text);
public String buttonText = (String) showFactButton.getText();
public boolean updateLaunchText() {
if (buttonText.equals(launchText)) {
buttonText.replaceAll(launchText, nextText);
return true;
}
else {
return true;
}
}
public void onClick(View view) {
String fact = mFactBook.getFact();
// Update the label with our dynamic fact
factLabel.setText(fact);
}
};
With the following added to strings.xml:
<string name="start_text">Try it out!</string>
<string name="next_text">Show another Fun Fact!</string>
No errors, but the button text stays on "Try it out!" I'm sure that all the extra objects are totally unnecessary compared to the first, working method for the scope of this app, but I'd still like to figure it out since I don't really have any idea what I'm doing with the boolean.
Questions: 1) What am I missing in the longer boolean approach? 2) What's the actual most efficient approach to accomplish this task?
Did you connect the listener to the button object?Without that connection no logic is applied to a button click.It goes like this:
buttonName.setOnClickListener(...)
You'd have to initialize the button object first though :)
Where r u call to method updateLaunchText() ?
you should change the objects to global object (not to create the into the listener):
private String launchText = getResources().getString(R.string.start_text);
private String nextText = getResources().getString(R.string.next_text);
private String buttonText = (String) showFactButton.getText();
and take the method updateLaunchText() out of the listener too.
and then into the onClick(View view) call to updateLaunchText() like this:
public void onClick(View view) {
updateLaunchText();
String fact = mFactBook.getFact();
// Update the label with our dynamic fact
factLabel.setText(fact);
}
I have two AutoCompleteTextView (group and instalation).
After I choose group, Instalation should filter the information depending on the group but it's not working.
If in the sql line i take out the WHERE part it works fine (but shows me all the information and i don't want that).
List<String> instalacao = new ArrayList<String>();
Cursor cursor=mydb.rawQuery("SELECT DISTINCT instalacao FROM registo WHERE grupo like '"+txGrupo.getText().toString()+"';",null);
while (cursor.moveToNext()){
instalacao.add(cursor.getString(cursor.getColumnIndex("instalacao")));
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.select_dialog_item,instalacao);
txInstalacao.setThreshold(0);
txInstalacao.setAdapter(adapter);
The dropdown:
txInstalacao.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
txInstalacao.showDropDown();
}
});
What am I doing wrong?
If you want to match a prefix, you should use '%' at the end of the parameter.
"WHERE grupo like '" + txGrupo.getText().toString() + "%'"
As an aside, I would strongly recommend using the query() method instead of rawquery(). Building an SQL statement like this will lead to problems (for example if the contents of txGrupo contains quotes).
I figured out why it wasnt showing anything. When i start the intent i call the method, at this time the TextField is empty so it has nothing there. when i choose my group i have to refresh the method and i was not doing that :)
On a button click I am reading some information from a file and I need to display this in a textview, this code works while I am in the activity with the layout but if I am in a different screen the same code doesn't work.
String sdcard = Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File(sdcard + "/Mult/","boardname.cfg");
//Read text from file
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
Global.defaultboard = line;
}
TextView defaultboard = (TextView) findViewById(R.id.currentboard);
defaultboard.setText(Global.defaultboard);
}
catch (IOException e) {
//You'll need to add proper error handling here
}
finish();
Can anyone see whats wrong? if I remove the lines aor comment the lines of the textview it doesn't crash.
Thanks
MrC
OK
My Solution is - my value is stored in a global variable so I use the onResume() like this to refresh the textview.
public void onResume()
{
super.onResume();
TextView defaultboard = (TextView) findViewById(R.id.currentboard);
defaultboard.setText(Global.defaultboard);
}
MrC
you can only update UI views when running in the main thread. If you do stuff in a different thread use the runOnUIThread method of the activity passing a little Runnable that does the actual work.
Well, each activities has his own layout so you can't update items through different activities directly.
What you need is to take a look at "Starting Activities and Getting Results"
Have you ever thought of using SharedPreferences?
Make a string for the text you want to display in this class.
Write this string to shared preferences using putString("key", value).
In the activity that has the TextView you need to update, initialize it to something as to not get a NullPointerException. Then load the string from your SharedPreferences and set the text from there.
If you want to be able to set it dynamically, you can make a updateText() method in the activity that has the TextView to change it, because if the activity is still running, it will not update as onCreate() is not called. Just be sure to check what state it's in, because if that activity is not currently in existence (onDestroy() has been called), you will get another exception.
Hope this helps. I have found that SharedPreferences are the answer to a lot of my problems. If you need help, just let me know and I'll try to help you out.
OK
My Solution is - my value is stored in a global variable so I use the onresume like this to refresh the textview
public void onResume()
{
super.onResume();
TextView defaultboard = (TextView) findViewById(R.id.currentboard);
defaultboard.setText(Global.defaultboard);
}
Thanks to everyone for answering, I like some of these ideas and am looking into how they work!
Is there any way that I can link a keyword in a TextView to a file or directory on the user's SD card? My app produces stack trace files when it crashes and I want the user to able to click a link in my About dialog to view either the latest one or the folder containing all of them. (Something like "If this app crashes, please send [link]the latest stack.trace file[/link] to us at myapp#example.com.")
I know it is possible to use the following code to make a Web link but I tried to modify it to use "file:///sdcard/path/to/file/stack.trace" which causes my app to Force Close when the link is clicked.
<string name="strSample">This is Web link to <a href="http://www.google.com">Google</a>!</string>
final TextView tvSample = (TextView)findViewById(R.id.tvSample);
tvSample.setMovementMethod(LinkMovementMethod.getInstance());
String strSample = getResources().getString(R.string.strSample);
tvSample.setText(Html.fromHtml(strSample));
You can extend your method by replacing Html.fromHtml(strSample) part which returns Spannable. Create your own Spannable and add ClickableSpan to it. In the onClick method you can place whatever logic you need. Here's quick examle that you can extend
public Spannable getProfileLink(final Context context) {
final String name = firstName + " " + lastName;
Spannable spans = SpannableStringBuilder.valueOf(name);
ClickableSpan clickSpan = new ClickableSpan() {
#Override
public void onClick(View widget) {
// TODO - call profile here
Toast.makeText(context, "Will call profile", Toast.LENGTH_LONG);
}
};
spans.setSpan(clickSpan, 0, name.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spans;
}