I'm creating an app where I need to quickly test some different languages. I've got 3 string resource files, values/strings.xml, values-es/strings.xml, and values-fr/strings.xml. Each of the files have their respective translated strings.
When I launch the app, I'm preloading some text into a TextView (Locale.getDefault().displayLanguage) and text that I pull in from an array in the xml file and assign one string to an EditText:
<string-array name="some_text">
<item>Overall, how severe were your flu symptoms today? Please select one response only.</item>
<item>No flu symptoms today</item>
<item>Mild</item>
<item>Moderate</item>
<item>Severe</item>
<item>Very Severe</item>
</string-array>
I set the text of the language label like this:
languageTxt = findViewById(R.id .language_text)
languageTxt.text = Locale.getDefault().displayLanguage
Then load the strings in the array and set one of them to the EditText like this:
textList = resources.getStringArray(R.array.some_text)
editTxt = findViewById(R.id.edit_text)
if(textList.isNotEmpty()) {
val txt = textList[currentIndex] //currentIndex = 0
editTxt.setText(txt)
}
textList, languageTxt, and editTxt are declared private like:
private lateinit var textList: Array<String>
private lateinit var languageTxt: TextView
private lateinit var editTxt: EditText
The first run through onCreate, everything works fine. If the language is set to Spanish, both languageTxt and editTxt are in Spanish as expected. Then if I go to settings and change the language to French, when I bring my app back to the foreground, the languageTxt says French (well spelled in French). Then I watch in the debugger, the textList loading the text, and it's all the French strings like I expected. The problem I'm seeing is when I set editText, the control isn't updating to display the French string. It's still in Spanish. I can clearly see that the text is in French, but calling setText() doesn't seem to be working. I've tried clearing the exitTxt first, setting it to null, empty, etc, nothing seems to work. Does anyone know what's going on here? I've been scratching my head for a couple hours. Ugh
Thanks to Giddy Naya's answer for giving me a hint on what is going on. Android saves the state of the app when it goes in the background so that it's the same when it comes back to the foreground. It's so strange, because even a editTxt.setText() doesn't work and gets overridden by Android. So what I had to do is set the new state of app (i.e. update the text) in the onResume function:
override fun onResume() {
super.onResume()
if(textList.isNotEmpty()) {
val txt = textList[currentIndex]
editTxt.setText(txt)
}
}
If you're new to Android, this feature can make debugging quite a pain, since you're trying to set a new state in onCreate and it doesn't change.
I'm still not sure why setting a TextView works in onCreate() but setting an EditText does not.
If your app is in foreground during language changes your UI may need reloading onResume so expected resources can be loaded.
You can save the default language in preference and check for value changes onActivityResume and if true then reload UI.
Something like
override fun onResume() {
super.onResume()
...
if (localeHasChanged)
setContentView(R.layout.xxx) //force UI reload
...
}
Related
var text:String = ""
var result = TextRecognition.getClient().process(image)
.addOnSuccessListener { visionText ->
text = visionText.text
Log.d("OUTPUT",visionText.text)
}
findViewById<TextView>(R.id.txt_Original).setText("ORIGNAL: "+text);
I'm giving the text recognition an image to read text from. I then want to assign that text to my variable "text". However, the text from the image isn't being assigned to my variable. I added a Log.d to see if anything is being read and the text from the photo is being read as it returns the correct text from the image.
I added the "ORIGNAL" to the setText just to make sure it isn't just skipping that line, and it is setting the text to "ORIGNAL: " but no text. But I know Its getting to that point
If I assign the TextView directly inside the addOnSucessListener, then it works. However, I need to do things to the text so I would like to keep it as a variable
After adding a Log after the function call, I found out that the log afterwards was running first and then the log inside the function ran. I'm assuming the function is acting asynchronous. Thus I moved all the code I wanted to run (basically all of it) into the addOnSuccessListener. Its messy but it runs now!
So I'm working on my first real attempt at an Android app, just a simple scorekeeper for softball games. I've got it tallying scores, outs, etc, and right now it just displays "Home" and "Away." I'd like to give users the chance to enter in actual team names. To this effect, I added a custom AlertDialog that pops up with an EditText, so when you hit "OK" it'll update the Home/Away team name.
The problem is I've been Googling this for most of the week and I've not found a single way to actually do this. I've tried tagging the fragment's layout XML so I can find the EditText, but it always gives me a null reference and crashes the app. I added a TextWatcher that presumably watched the fragment's text, but once changed and hit "OK," nothing happened. Tried adding the TextWatch to the fragment, that crashed I think, it was about two hours ago and I'm exhausted.
Really, I think I need a way to have the fragment find the TextView with the team name and change it to the value of the EditText when I positive click, but I don't know how to do that. Or maybe I've seen it and don't understand it, I've only been doing this about two months. I'd post my code, but I deleted out all the stuff that didn't work because it was taking up most of the screen real estate. Any ideas?
EDIT: So I followed advice below on defining views, that found the value of the EditText presumably, but hitting "OK" just made it set the TextView to a blank value. I think this is because the EditText's contents went away as the dialog was closed. Either that or this is all wrong. View dialogname = getActivity().getLayoutInflater().inflate(R.layout.fragment_home, null);
EditText mEtName = (EditText) dialogname.findViewById(R.id.homeName);
View mainAct = getActivity().getLayoutInflater().inflate(R.layout.activity_softball, null);
TextView oTextView = (TextView) mainAct.findViewById(R.id.teamOne);
newName = mEtName.getText().toString();
oTextView.setText(newName)
I think you are doing wrong at time of defining id for EditText. You need to give it dialog reference.
rather than doing
Edittext edittext = (EditText) findViewById(R.id.editText);
do like
Edittext edittext = (EditText) dialog.findViewById(R.id.editText);
Been through this issue a while ago. I created my own class which extended DialogFragment. When I tried to initialize EditText which was in the dialog, I got null like
mEtName = (EditText)dialog.findViewById(R.id.editText);
So, I initialized it in this way and it worked:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
View dialogName = getActivity().getLayoutInflater().inflate(R.layout.dialog_name, null);
mEtName = (EditText) dialogName.findViewById(R.id.dialog_etxt_name);
}
Where R.layout.dialog_name is my custom dialog layout.
I am developing a PreferenceActivity where I can add CheckBoxPreference instances according to some dynamic content. I also maintain a count of the checked preferences in the activity. Everything is good when I load the application for the first time. But when I select some 2-3 check boxes and deploy the application code again on emulator, the previously selected check boxes just remain checked when I come back to same activity. The same happens when I move to and from some activities within the same application!
To prevent this, every time when I create an instance of CheckBoxPreference, I explicitly call .setChecked(false)!!! But still those previously checked preferences remain checked only!
I can't understand the behavior! Does it bring those values checked from cache! But I explicitly call .setChecked(false), what about that then?
Thank you very much,
Ketan
EDIT : Here is my code:
String content = null;
for (String title : titles) {
checkBoxPref = new CheckBoxPreference(this);
checkBoxPref.setKey(title);
checkBoxPref.setTitle(title);
<b>checkBoxPref.setDefaultValue(Boolean.FALSE); //Line # 1 set default to false
checkBoxPref.setChecked(false);//Line # 2 set checked = false </b>
content = config.getString(title, "Yet to define!");
if (content.length() > 30) {
content = content.substring(0, 30);
}
checkBoxPref.setSummary(content);
checkBoxPref.setOnPreferenceChangeListener(new MyCheckBoxChangeListener());
checkBoxPreferenceList.add(checkBoxPref);
inlinePrefCat.addPreference(checkBoxPref);
}
This code is executed everytime I app comes back to this activity! But still had I checked 2-3 checkboxes before leaving this activity, they will remain in the same state when app comes back to this! Please have a look at the code, I am already setting setChecked(false) explicitly, but still can't get them unchecked!
Please suggest some solution! I am stuck!
You will probably have to post some code to get a better answer. I had this same issue when I had my checkbox inside my adapter. I got around the issue by handling the checkbox with an onClickListener:
CheckBox menuOption = (CheckBox) v.findViewById(R.id.list_checkbox);
menuOption.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
CompoundButton cb = (CompoundButton) v;
// code to set preference goes here
// can check if true or false with cb.isChecked()
}});
My app has this appearance
It seems to be a TableLayout with several TableRows. In my activity, each TableRow has 3 views: ImageView, TextView and a Button.
The user is the one who sets the content of the ImageView and the TestView by entering the text he wants and pressing a button.
I store this data in stringArray variables and works fine if the phone is not restarted or the app is not closed (forceClose)
If one of these two situations happen, i lose all my data.
I've been trying to store my StringArrays by SharedPreferences but I don't know when i should load the preferences, whether it's in OnCreate() or OnResume() or OnStart methods().
Another question is how to define the arrays. I use this:
String[] titulo = new String[500];
I don't know if this string is created each time i start the activity. Because what i want is to load the previous String (from SharedPreferences) and add some more entries not to create new ones every time the phone is rebooted, for example.
Do you think i need a SQL database or it's OK with this StringArrays.
Thank you.
You should probably switch to using a database, seeing as you have an array of size 500, which could possibly increase in the future.
However, if you want to continue using SharedPreferences, you should write the data in onPause() and onStop() methods, and use an if else statement to see if your data is null before running an operation on it. If the data is null, the read it from the SharedPreferences before continuing.
Running my application causes ~40% CPU usage on my Phone:
final String position = String.format("%02d:%02d:%02d", time.getHours(), time.getMinutes(),
time.getSeconds());
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
c.mTxtPosition.setText(position);
...
By commenting out the setText method the CPU Usage drops to the expected level of ~4%. The method is invoked every second and does refresh ImageViews, CustomViews ... without causing the same load excess.
Besides the CPU Usage dalvik constantly reports garbage collecting of about 10-1000 objects just by calling setText().
Creating a tracefile like this:
Debug.startMethodTracing("setText");
c.mTxtPosition.setText(position);
Debug.stopMethodTracing();
traceview lists the following methods as Top 5 by their respective exclusive CPU%:
ViewParent.invalidateChildInParent(16%)
View.requestLayout(11%)
ViewGroup.invalidateChild(9%)
TextView.setText(7%)
toplevel(6%)
Has anybody an explanation for this?
I noticed this myself a while ago, I think the problem is that every time you call setText, the size of the textbox can change, thus requiring the entire screen to go through relayout (expensive).
I haven't tried this myself yet, but if your textbox is simple and can be made to be a relatively fixed size, maybe try to subclass TextView and create a view that does not resize itself on setText, but rather just draws whatever it can into the existing area? That would save a lot of time.
Perhaps theres already a flag to setText that can make it do this, but I'm not aware of it, though I haven't searched closely.
In my case, I update a TextView from touch event, which cause a lot of updating The solution was to change the TextView layout_width & layout_height to fixed sized.
some possible improvements :
try using a handler which updates the textview every 0.5 seconds instead of a thread that does it.
make the runnable a final constant object instead of craeting a new one every second.
consider checking that the time has changed (newTimeInMs-LastPublishedTimeInMs>=1000) before telling the textview to update itself.
instead of String.format , try using StringBuilder . however , you won't enjoy the locale solution that the String.format gives (for example , for arabic digits) .
In my case it was this property of TextView:
android:ellipsize="marquee"
Removing it speeded up setting text.
If you look at the source code of setText method you can see that it does a lot of heavy lifting - there is measuring, drawing and object allocations, all of which run on the main thread.
You can use the new PrecomputedText API in order to do all of this on the background thread and make setText faster.
You can use the following working example using kotlin & coroutines
private fun TextView.setTextAsync(text: String) {
val textView = this
lifecycleScope.launch {
val params = TextViewCompat.getTextMetricsParams(textView)
val precomputedText = withContext(Dispatchers.Default) {
PrecomputedTextCompat.create(text, params)
}
TextViewCompat.setPrecomputedText(textView, precomputedText)
}
}
For more details you can read an article about it on my blog
https://androidexplained.github.io/android/ui/2020/10/21/improving-textview-settext-performance.html