Well as the title states, anytime I try (in my java class) to settext of a TextView by directing it set the text of a string listed in "strings.xml" my program crashes, If i remove that call then the program runs fine. Below is an example.
MediaPlayer dus;
String Stat;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
final TextView T = (TextView) findViewById(R.id.Status);
dus = MediaPlayer.create(DialUpDroidActivity.this, R.raw.dus);
Timer timer;
timer = new Timer();
dus.start();
Stat = getString(R.string.Dial);
TimerTask TxtTimer = new TimerTask() {
public void run() {
T.setText(Stat);
}
};
timer.schedule(TxtTimer, 7000);
}
So as you can see i tried to do T.setText(Stat); but the program crashed. I've tried T.setTextView(R.string.Dial); and T.setTextView("Hello") Both methods crashed. What am I doing wrong?
Have you initiliazed your textview?
TextView T = (TextView)findViewById(R.id.yourId);
Where is
T = (TextView)findById(...)
?
Use
getString(R.string.XXX)
Related
I'm trying to make messages like in messenger. They must appear one after another. So I use the LinearLayout and add the TextView to it. But the appear all at once. I use the loop, but it looks like it doesn't work!
Here is the code
final LinearLayout lm = (LinearLayout) findViewById(R.id.line_layout);
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(10, 10, 500, 50);
int i = 0;
for (final Task task : tasks) {
i = i + 1;
for (int j = 0; j < 1; j++) {
final TextView message = new TextView(TaskActivity.this);
message.setText(task.getName());
message.setId(task.getId());
message.setLayoutParams(params);
message.setTextSize(30);
message.setBackground(getApplicationContext().getDrawable(R.drawable.task_text));
Toast.makeText(TaskActivity.this, "Text loaded",
Toast.LENGTH_SHORT).show();
lm.addView(message);
SystemClock.sleep(1000);
}
}
The TextViews appear at once no matter the timer. The app waits while the Timer for every circle of the loop and returns the hole messengers at once!
See the screenshot of the app:
So how would you do this task and resolve the problem? Thank you!
If you want the behaviour as in Messenger , you should use RecyclerView in android.
https://developer.android.com/guide/topics/ui/layout/recyclerview
With the time interval to add a new message, you can use recyclerview notify methods to show the new messages.
define a layout in which you need to add your textView and then do the following
LayoutParams lparams = new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
TextView tv=new TextView(this);
tv.setLayoutParams(lparams);
tv.setText("test");
this.parentLayout.addView(tv);
Your code is running on the uiThread so the UI doesn't update until the loop is complete. Have a look at using an AsyncTask to pause the app in the background and do the update after finishing. Try something like this:
public class TestActivity extends Activity
{
Queue<String> messages = new LinkedList<String>();
class PushNextMessage extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... params)
{
try
{
Thread.sleep(1000);
}
catch (Exception ex)
{
ex.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void _void)
{
String message = messages.remove();
//this is where you add the view to the base layout
if (messages.size() > 0)
{
new PushNextMessage().execute();
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
messages.add("message 1");
messages.add("message 2");
messages.add("message 3");
new PushNextMessage().execute();
}
}
I have a list of buttons and what I want to do is display some information on press. Here´s the code:
public class ActividadDos extends AppCompatActivity {
private Map<CharSequence, String> info = new HashMap();
private Button btnYogur;
private Button btnChocolate;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_actividad_dos);
btnYogur = (Button) findViewById(R.id.btnYogur);
btnChocolate = (Button) findViewById(R.id.btnChocolate);
info.put(btnYogur.getText(), "Lácteos");
info.put(btnChocolate.getText(), "Grasas, aceites y dulces");
}
public void displayMensaje(View v) {
Button button = (Button) v;
String nombre = (String) button.getText();
String mensaje = "Clasificación: " + info.get(nombre);
Toast.makeText(ActividadDos.this, mensaje, Toast.LENGTH_SHORT).show();
}
}
It doesn´t show any errors but when I press the buttons it doesn´t display the message.
Similar code is working on another activity.
You forgot to call displayMensaje() method.
Add this to .xml for corresponding button(As per requirement)
android:onClick="displayMensaje"
It isn't displaying anything because you aren't calling displayMensaje() method anywhere in your code at all. To solve this, please add a call to this method and your problem will be solved.
It is always the little things that stump me for hours.
I have an onPostExecute method from an AsyncTask class that looks like so:
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
showColumnCounts();
dataDownloadCompleteToast();
}
The toast works just fine. However, my showColumnCounts() method refuses to work. It works just fine on the main thread. I use it during onCreate() just not here. I thought the onPostExecute ran on the UI thread?
Here is my showColumnCounts() method if it is relevant.
public void showColumnCounts() {
TextView totalView = (TextView) findViewById(R.id.totalColumn2);
TextView ignoredView = (TextView) findViewById(R.id.ignoredColumn2);
TextView rView = (TextView) findViewById(R.id.rColumn2);
Cursor c = myDB.getEmptyRColumn("");
int count = c.getCount();
if (count == 0) {
c.close();
return;
}
String unread = String.valueOf(count);
String total = getTotalCount();
int tTotal = Integer.parseInt(total);
int r = tTotal - count;
String read = String.valueOf(r);
totalView.setText(total);
ignoredView.setText(unread);
rView.setText(read);
c.close();
}
I've been fiddling with it for a while now assuming the answer should be obvious but I'm calling uncle. Can't figure it.
Edit***** 6/30
I THINK I've found my problem. In my background thread I am using a parse.com method "query.findInBackground" which I assume is starting a third thread? I'm trying to update this to "query.find" and I'm hoping that will fix.
First of all you should move all your TextView declarations inside your onCreate method
if you want to change or perform some UI operation, if you want to perform some non UI based operations while the thread is running then do that in doInBackground() method
You should move …setText(...) lines into
runOnUiThread(new Runnable(){
void run(){
// UI stuff
});
You need to tell where is your async class located and the showColumnCounts() function located.
If they both where in different class then you should create a context to call the function from the async class.
Take this as example and try.
Example:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.main);
new AsyncClass(this);
super.onCreate(savedInstanceState);
}
public void showColumnCounts() {
TextView totalView = (TextView) findViewById(R.id.totalColumn2);
TextView ignoredView = (TextView) findViewById(R.id.ignoredColumn2);
TextView rView = (TextView) findViewById(R.id.rColumn2);
Cursor c = myDB.getEmptyRColumn("");
int count = c.getCount();
if (count == 0) {
c.close();
return;
}
String unread = String.valueOf(count);
String total = getTotalCount();
int tTotal = Integer.parseInt(total);
int r = tTotal - count;
String read = String.valueOf(r);
totalView.setText(total);
ignoredView.setText(unread);
rView.setText(read);
c.close();
}
public class AsyncClass extends AsyncTask<String, Void, Boolean> {
private Activity activity;
public AsyncClass(Activity main_activity) {
this.activity = main_activity;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
activity.showColumnCounts();
dataDownloadCompleteToast();
}
}
}
If you want to do some UI change process in background running operation(ASYNC TASK),you write that codes in UI thread. Example:
YourActivity.this.runOnUiThread(
new Runnable()
void run()
{
//UI changes
showColumnCounts();
});
I'm creating a simple app with two NumberPickers used to select a certain number of minutes and seconds. There isn't too much code so I will post it here:
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = "Interval Trainer";
private CountDownTimer countDownTimer;
private boolean timerHasStarted = false;
private Button startButton;
public TextView text;
private final long interval = 1 * 1000;
//Create NumberPickers
NumberPicker numberPicker1 = (NumberPicker) findViewById(R.id.numberPicker1);
NumberPicker numberPicker2 = (NumberPicker) findViewById(R.id.numberPicker2);
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG,"Entering onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startButton = (Button) this.findViewById(R.id.button);
startButton.setOnClickListener(this);
text = (TextView) this.findViewById(R.id.timer);
//Set min and max values for NumberPickers
numberPicker1.setMaxValue(100);
numberPicker1.setMinValue(0);
numberPicker2.setMaxValue(59); //This is the seconds picker
numberPicker2.setMinValue(0);
Log.i(TAG,"Exiting onCreate()");
}
#Override
public void onClick(View v) {
//Calculate total time from NumberPickers in seconds
long startTime = (numberPicker1.getValue() * 60) + numberPicker2.getValue();
//Create CountDownTimer with values from NumberPickers
countDownTimer = new MyCountDownTimer(startTime, interval);
text.setText(text.getText() + String.valueOf(startTime / 1000)); //should be removed
if(!timerHasStarted) {
countDownTimer.start();
timerHasStarted = true;
startButton.setText("STOP");
} else {
countDownTimer.cancel();
timerHasStarted = false;
startButton.setText("RESTART");
}
//Disable the NumberPickers after 'Start' is pressed
numberPicker1.setEnabled(false);
numberPicker2.setEnabled(false);
}
public class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
#Override
public void onFinish() {
text.setText("Time's up!");
//re-enable the NumberPickers once countdown is done
numberPicker1.setEnabled(true);
numberPicker2.setEnabled(true);
}
#Override
public void onTick(long millisUntilFinished) {
text.setText("" + millisUntilFinished / 1000);
//Changes the value of the NumberPickers after each tick
}
}
}
I have a feeling the crash is related to me declaring the two NumberPickers outside of any methods (this would automatically make them static?). Originally I had these two lines of code in my onCreate() but since I needed them in my inner class and other methods I moved it outside. Is this what is causing the crash? If so, how do I do this correctly and still have access to numberPicker1 and 2 all around my class (including inner class)?
Thank you!
You cant intiate object like this
//Create NumberPickers
NumberPicker numberPicker1 = (NumberPicker) findViewById(R.id.numberPicker1);
NumberPicker numberPicker2 = (NumberPicker) findViewById(R.id.numberPicker2);
after onCreate only you layout loads so you dont have you object yet initialized.
You can initlize you object in onCreate after
setContentView(R.layout.activity_main);
For example
// init variable
NumberPicker numberPicker1 = null;
NumberPicker numberPicker2 = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
// After here only your Activity gets the layout objects
numberPicker1 = (NumberPicker) findViewById(R.id.numberPicker1);
numberPicker2 = (NumberPicker) findViewById(R.id.numberPicker2);
}
You should put your findViewById inside onCreate method and create local variables:
// init variable
NumberPicker numberPicker1, numberPicker2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
numberPicker1 = (NumberPicker) findViewById(R.id.numberPicker1);
numberPicker2 = (NumberPicker) findViewById(R.id.numberPicker2);
}
Then, you will able to call these variables inside other methods. According to this reference:
Non-static nested classes (InnerClasses) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class. [...] InnerClass has direct access to the methods and fields of its enclosing instance.
Can anyone help me work out where I'm going wrong here. On the button click the media player plays one of the mfiles at random and I'm trying to set a textview depending on which file was played. Currently the setText if statements only match the audio playing half the time. Really not sure where I'm going wrong here.
private final int SOUND_CLIPS = 3;
private int mfile[] = new int[SOUND_CLIPS];
private Random rnd = new Random();
MediaPlayer mpButtonOne;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mfile[0] = R.raw.one;
mfile[1] = R.raw.two;
mfile[2] = R.raw.three;
//Button setup
Button bOne = (Button) findViewById(R.id.button1);
bOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final TextView textOne = (TextView)findViewById(R.id.textView1);
mpButtonOne = MediaPlayer.create(MainActivity.this, mfile[rnd.nextInt(SOUND_CLIPS)]);
if (mpButtonOne==null){
//display a Toast message here
return;
}
mpButtonOne.start();
if (mfile[rnd.nextInt(SOUND_CLIPS)] == mfile[0]){
textOne.setText("one");
}
if (mfile[rnd.nextInt(SOUND_CLIPS)] == mfile[1]){
textOne.setText("two");
}
if (mfile[rnd.nextInt(SOUND_CLIPS)] == mfile[2]){
textOne.setText("three");
}
mpButtonOne.setOnCompletionListener(new soundListener1());
{
}
So just to clarify the problem I am having is that the setText only matches the audio occasionally, not on every click. The rest of the time it displays the wrong text for the wrong audio.
You are choosing another random file
mfile[rnd.nextInt(SOUND_CLIPS)]
set that to a variable in onClick() then check against that variable in your if statement
public void onClick(View v) {
int song = mfile[rnd.nextInt(SOUND_CLIPS)];
final TextView textOne = (TextView)findViewById(R.id.textView1);
mpButtonOne = MediaPlayer.create(MainActivity.this, song);
if (song == mfile[0]){
textOne.setText("one");
}
Edit
To make it a member variable so you can use it anywhere in the class, just declare it outside of a method. Usually do this before onCreate() just so all member variables are in the same place and it makes your code more readable/manageable.
public class SomeClass extends Activity
{
int song;
public void onCreate()
{
// your code
}
then you can just initialize it in your onClick()
public void onClick(View v) {
song = mfile[rnd.nextInt(SOUND_CLIPS)];
final TextView textOne = (TextView)findViewById(R.id.textView1);
mpButtonOne = MediaPlayer.create(MainActivity.this, song);