3

I create textView in scrollView. Every time i setText the textView, the text not updating, but when i open the keyboard then close it, the text updated.. after googling, i got the solution is call textView.invalidate() and textView.requestLayout(). But i am currious why it's not updating without call invalidate and requestLayout? Is scrollView has somethis 'special' so i need to call invalidate and requestLayout?

here is the code

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.zihadrizkyef.belajarinternalstorage.MainActivity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="8"
        android:orientation="vertical">

        <EditText
            android:id="@+id/etWrite"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="5"
            android:gravity="top"
            android:hint="write text here"/>
        <View android:id="@+id/separator1"
              android:layout_width="match_parent"
              android:layout_height="1px"
              android:layout_marginTop="20dp"
              android:layout_marginBottom="20dp"
              android:background="#aaa"/>
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <TextView
                android:id="@+id/tvRead"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:gravity="center"
                android:hint="(no text)"/>
        </ScrollView>
        <View android:id="@+id/separator2"
              android:layout_width="match_parent"
              android:layout_height="1px"
              android:layout_marginTop="20dp"
              android:layout_marginBottom="20dp"
              android:background="#aaa"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="horizontal"
        android:layout_weight="2"
        android:gravity="center">

        <Button
            android:id="@+id/btnSave"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:onClick="onClick"
            android:text="save"/>
        <Button
            android:id="@+id/btnLoad"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:onClick="onClick"
            android:text="load"/>
    </LinearLayout>
</LinearLayout>

MainActivity.java

package com.zihadrizkyef.belajarinternalstorage;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
    private final String FNAME = "mydata";
    EditText etWrite;
    TextView tvRead;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        etWrite = (EditText)findViewById(R.id.etWrite);
        tvRead = (TextView)findViewById(R.id.tvRead);
    }


    public void onClick(View v) {
        switch(v.getId()) {
            case R.id.btnSave:
                String data = etWrite.getText().toString();
                try {
                    FileOutputStream fOut = openFileOutput(FNAME, MODE_PRIVATE);
                    fOut.write(data.getBytes());
                    fOut.close();
                    Toast.makeText(MainActivity.this, "File saved", Toast.LENGTH_SHORT).show();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            break;
            case R.id.btnLoad:
                int cRead;
                String read="";

                try {
                    FileInputStream fIn = openFileInput(FNAME);
                    while((cRead=fIn.read())!=-1) {
                        read += Character.toString((char)cRead);
                    }
                    tvRead.setText(read);
                    tvRead.invalidate();
                    tvRead.requestLayout();
                    Toast.makeText(MainActivity.this, "File loaded", Toast.LENGTH_SHORT).show();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            break;
        }
    }
}

github : https://github.com/zihadrizkyef/FileWriteRead_InternalStorage

zihadrizkyef
  • 1,390
  • 2
  • 12
  • 33
  • 1
    the textview doesnt refresh constantly to save performence, by opening and closing you reload it or by invalidating and requesting the layout you also reaload it. this is the same when you are using things like the android gallery. i hope this helped :) – Just_someone Sep 26 '16 at 14:47
  • Can you elaborate a little bit more the scenario of saving and loading the text? I'm asking for it because I used your code with the `requestLayout` and `invalidate` commented, and it works as expected since those 2 methods are called at the end of `setText` method. As a last thing, add the device and android version you are testing, since the problem might be from there – Iulian Popescu Sep 26 '16 at 15:35
  • @Just_someone thanks broh, but can you prove it? such an article or scrollview source code :D – zihadrizkyef Sep 26 '16 at 23:36
  • @IulianPopescu write something in edit text (automatically your android keyboard opened), then click save button (so keyboard closed), then click the load button you will see the textView not updating. Then you click on the EditText (so keyboard opened) then close the keyboard without do any change on the editText (and dont click the save and load button). Then you will see the textView updated. I am using android kitkat (4.4.2) :D – zihadrizkyef Sep 26 '16 at 23:36
  • 1
    @ZihadRizkyEdwinFikri i was unable to find an article like this but i did have 3 phones running a refresh test all night which led me to conclude that the mail layout refreshes every 2-5 seconds (depending on the phone) or on update. but in a secondary layout it would only reload once every few minutes or on some phones not even that. Good luck with your project. – Just_someone Sep 27 '16 at 07:10
  • 1
    @ZihadRizkyEdwinFikri I tried as you said and everything works for me. As soon as I tap the save button a `Toast` with the save message is showed and when I tap the load button, the `TextView` is updated and the `Toast` showed. Do you have some other code that might create this problem or everything is on github? – Iulian Popescu Sep 27 '16 at 08:13
  • What's your android version? I don't know. It might be the problem is from my phone. – zihadrizkyef Sep 27 '16 at 13:46
  • I tested on a Nexus 5X with Android N, but I tries also with some emulators with different Android versions and everything looks fine – Iulian Popescu Sep 28 '16 at 08:14

3 Answers3

0

You can try updating the value using AsyncTask. As the method onPostExecute() runs in UI thread, it can make any kind of UI updates dynamically. Refer to this for more info:https://developer.android.com/reference/android/os/AsyncTask.html

Rishabh Kumar
  • 467
  • 3
  • 12
0

you've set ScrollView's height and TextView's height to "0" and don't have any text set for TextView,so you have to invalidate your view in order to measure its layout parameters again.

you can use this link: Making TextView scrollable on Android

Community
  • 1
  • 1
Farid
  • 823
  • 7
  • 13
  • Having the height set to `0` doesn't mean that the actual height of view will be `0`. If you pay a little attention to the code, you'll see that he uses the `weight` property to make the views fill its parent. Please read the code before posting something – Iulian Popescu Sep 26 '16 at 15:28
-1

Its obvious, Whenever you change the data for a control it doesn't get reflected in the view, unless the control or its parent control or view is invalidated.

Its also mentioned in documentation of TextView https://developer.android.com/reference/android/widget/TextView.html#setText(char[], int, int)

njzk2
  • 37,030
  • 6
  • 63
  • 102
Ashish Rawat
  • 4,674
  • 1
  • 16
  • 16
  • 1
    that's not what the doc means (also, that's not the method the OP is using). The doc says that if you pass a `char[]`, and make subsequent modification *to the content of the char[]*, the TextView can't know about it. But *obviously*, if when you call `setText`, the modification is reflected on the view*. (unless specific cases) – njzk2 Sep 26 '16 at 15:26