jak zmienić tekst w Android TextView

92

Próbowałem to zrobić

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    t=new TextView(this); 

    t=(TextView)findViewById(R.id.TextView01); 
    t.setText("Step One: blast egg");

    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    t.setText("Step Two: fry egg");

ale z jakiegoś powodu po uruchomieniu pojawia się tylko drugi tekst. Myślę, że może to mieć coś wspólnego z Thread.sleep()blokowaniem metody. Czy ktoś może mi więc pokazać, jak zaimplementować licznik czasu „asynchronicznie”?

Dzięki.

user270811
źródło
2
Powodem, dla którego pokazuje tylko drugą linię, jest to, że .setText()zastępuje cały „widżet” tekstem, który każesz mu ustawić; WŁĄCZAJĄC tekst, który już tam umieściłeś.
georgiaboy82

Odpowiedzi:

45

Właśnie opublikowałem tę odpowiedź w grupie dyskusyjnej Google na temat Androida

Jeśli próbujesz tylko dodać tekst do widoku, tak aby wyświetlał się „Krok pierwszy: wysmaż jajko Krok drugi: smaż jajko” Rozważ użycie t.appendText("Step Two: fry egg"); zamiastt.setText("Step Two: fry egg");

Jeśli chcesz całkowicie zmienić to, co jest w TextViewśrodku, tak aby podczas uruchamiania wyświetlał się komunikat „Krok pierwszy: wydmuchaj jajko”, a następnie powiedział „Krok drugi: smaż jajko” po jakimś czasie, zawsze możesz użyć

Wykonalny przykład podany przez sadboya

Powodzenia

snctln
źródło
146

Twoja onCreate()metoda ma kilka ogromnych wad:

1) onCreate przygotowuje Twoje działanie - więc nic, co tu robisz, nie będzie widoczne dla użytkownika, dopóki ta metoda się nie zakończy! Na przykład - nigdy nie będziesz mógł zmienić TextViewtutaj tekstu więcej niż JEDEN raz, ponieważ tylko ostatnia zmiana zostanie narysowana, a tym samym widoczna dla użytkownika!

2) Pamiętaj, że program na Androida - domyślnie - działa tylko w JEDNYM wątku! Dlatego: nigdy nie używaj Thread.sleep()ani Thread.wait()w głównym wątku, który jest odpowiedzialny za Twój interfejs użytkownika! ( aby uzyskać więcej informacji, przeczytaj „Utrzymuj responsywność aplikacji” )

To, co robi inicjalizacja działania, to:

  • bez powodu tworzysz nowy TextViewobiekt t!
  • później wybierzesz układ TextVieww zmiennej t.
  • ustawiasz tekst t(ale pamiętaj: będzie on wyświetlany dopiero po onCreate() zakończeniu pracy i uruchomieniu głównej pętli zdarzeń Twojej aplikacji!)
  • czekasz 10 sekund w swojej onCreatemetodzie - nigdy nie wolno tego robić, ponieważ zatrzymuje to całą aktywność interfejsu użytkownika i na pewno wymusi ANR (aplikacja nie odpowiada, patrz link powyżej!)
  • następnie ustawiasz inny tekst - ten zostanie wyświetlony, gdy tylko onCreate()zakończy się Twoja metoda i kilka innych metod cyklu życia działania zostanie przetworzonych!

Rozwiązanie:

  1. Ustaw tekst tylko raz onCreate()- musi to być pierwszy tekst, który powinien być widoczny.

  2. Utwórz a RunnableiHandler

    private final Runnable mUpdateUITimerTask = new Runnable() {
        public void run() {
            // do whatever you want to change here, like:
            t.setText("Second text to display!");
        }
    };
    private final Handler mHandler = new Handler();
    
  3. zainstaluj to runnable jako handler, możliwe w onCreate()(ale przeczytaj moją radę poniżej):

    // run the mUpdateUITimerTask's run() method in 10 seconds from now
    mHandler.postDelayed(mUpdateUITimerTask, 10 * 1000);
    

Rada: upewnij się, że znasz Activitycykl życia! Jeśli będziesz robić takie rzeczy, stanie się onCreate()to tylko wtedy, gdy Twój Activityzostanie utworzony po raz pierwszy! Android prawdopodobnie utrzyma Cię Activityprzy życiu przez dłuższy czas, nawet jeśli nie jest widoczny! Kiedy użytkownik „uruchomi” go ponownie - a on nadal istnieje - nie zobaczysz już swojego pierwszego tekstu!


=> Zawsze instaluj programy obsługi onResume()i wyłączaj je onPause()! W przeciwnym razie będziesz otrzymywać „aktualizacje”, gdy Twój Activitynie będzie w ogóle widoczny! W twoim przypadku, jeśli chcesz zobaczyć swój pierwszy tekst ponownie, gdy zostanie ponownie aktywowany, musisz go ustawić onResume(), a nie onCreate()!

Zordid
źródło
14

Pierwsza linia nowego widoku tekstu jest niepotrzebna

t=new TextView(this); 

możesz to zrobić

TextView t = (TextView)findViewById(R.id.TextView01);

jeśli chodzi o wątek w tle, który tu śpi, jest przykładem, ale myślę, że istnieje zegar, który byłby lepszy do tego. tutaj jest link do dobrego przykładu z użyciem licznika czasu http://android-developers.blogspot.com/2007/11/stitch-in-time.html

    Thread thr = new Thread(mTask);
    thr.start();
}

Runnable mTask = new Runnable() {
    public void run() {
        // just sleep for 30 seconds.
                    try {
                        Thread.sleep(3000);
                        runOnUiThread(done);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
        }
    };

    Runnable done = new Runnable() {
        public void run() {
                   // t.setText("done");
            }
        };
Patrick Kafka
źródło
6

@ user264892

Zauważyłem, że używając zmiennej typu String potrzebowałem poprzedzić ciągiem „” lub jawnie rzutować na CharSequence.

Więc zamiast:

String Status = "Asking Server...";
txtStatus.setText(Status);

próbować:

String Status = "Asking Server...";
txtStatus.setText((CharSequence) Status);

lub:

String Status = "Asking Server...";    
txtStatus.setText("" + Status);

lub, ponieważ twój ciąg nie jest dynamiczny, jeszcze lepiej:

txtStatus.setText("AskingServer...");
jwalton85
źródło
3

zgodnie z twoją radą używam handle i runnables do przełączania / zmiany zawartości TextView przy użyciu „timera”. z jakiegoś powodu aplikacja zawsze pomija drugi krok („Krok drugi: smaż jajko”) i wyświetla tylko ostatni (trzeci) krok („Krok trzeci: podaj jajko”).

TextView t; 
private String sText;

private Handler mHandler = new Handler();

private Runnable mWaitRunnable = new Runnable() {
    public void run() {
        t.setText(sText);
    }
};

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    mMonster = BitmapFactory.decodeResource(getResources(),
            R.drawable.monster1);

    t=new TextView(this); 
    t=(TextView)findViewById(R.id.TextView01); 

    sText = "Step One: unpack egg";
    t.setText(sText);

    sText = "Step Two: fry egg";        
    mHandler.postDelayed(mWaitRunnable, 3000);

    sText = "Step three: serve egg";
    mHandler.postDelayed(mWaitRunnable, 4000);      
    ...
}
user270811
źródło
1
To nie może zadziałać! Jest tylko JEDEN program obsługi - jak chcesz, aby Twój jedyny istniejący runner mWaitRunnable „wiedział”, że sText był kiedyś ustawiony na „Krok drugi”, a następnie na „Krok trzeci” !! ?? Do pierwszego wywołania (po 3 sekundach) - wartość sText to po prostu „Krok trzeci”! Powinieneś zapoznać się z podstawowymi umiejętnościami Java przed wypróbowaniem programowania na Androida! :-)
Zordid
właściwie to, co w końcu zrobiłem, to dodanie licznika do runnable, jeśli jest 1, tekst będzie taki, jeśli jest 2, tekst będzie taki, itd.
user270811
0

:) Używasz wątku w niewłaściwy sposób. Po prostu wykonaj następujące czynności:

private void runthread()
{

splashTread = new Thread() {
            @Override
            public void run() {
                try {
                    synchronized(this){

                        //wait 5 sec
                        wait(_splashTime);
                    }

                } catch(InterruptedException e) {}
                finally {
                    //call the handler to set the text
                }
            }
        };

        splashTread.start(); 
}

Otóż ​​to.

jitain sharma
źródło
0

ustawienie tekstu na sam textview dwukrotnie powoduje nadpisanie pierwszego napisanego tekstu. Więc za drugim razem, kiedy używamy settext, po prostu dodajemy nowy ciąg, np

textview.append("Step Two: fry egg");
Disha
źródło
0

@Zordid @Iambda Odpowiedź jest świetna, ale znalazłem to, jeśli wstawię

mHandler.postDelayed(mUpdateUITimerTask, 10 * 1000);

w metodzie run () i

mHandler.postDelayed(mUpdateUITimerTask, 0);

w metodzie onCreate spraw, aby rzecz była aktualizowana.

Kevin Zhao
źródło