Search code examples
androidlayout-inflatercustom-view

Updating Android UI from custom view


I'm new to Android development, and still having difficulties comprehending how the framework works. I try to write a simple game to get some experience and I'd like to ask for some help with the below. In my main Activity, I have a few TextViews to show various data from my game, and under those I have a custom View called AnimatedView that has the canvas where I draw my objects for the game itself. Based on the objects on the Canvas, I'd like to update the TextViews to show e.g. number of object, what level the player is at, etc.

The problem is, even though I can get the TextView object with the below code, when I call textView.setText(...), nothing changes on the UI.

The below is a simplified version of my real code, to demonstrate the problem:

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    ...
    tools:context="com.danielsh.test.teststuff.MainActivity"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/myTextView"
        android:text="Change this!" />

    <com.danielsh.test.teststuff.AnimatedView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/animView" />

</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

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

AnimatedView.java

public class AnimatedView extends View {
    public AnimatedView(Context context, AttributeSet attrs) {
        super(context, attrs);

        final Handler uiHandler = new Handler();
        final Runnable runnable = new Runnable() {
            public void run() {
                LayoutInflater inflater = LayoutInflater.from(getContext());
                LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.activity_main, null, false);
                TextView textView = (TextView) layout.findViewById(R.id.myTextView);
                textView.setText("" + (System.currentTimeMillis() / 1000));
                textView.invalidate();
            }
        };

        uiHandler.postDelayed(runnable, 1000);
    }
}

I assume that I'm not working with the actual TextView object that's visible on the UI, but not sure what'd be the correct way of doing that.

Any help or pointer to an existing post that deals with the same problem would be much appreciated.


Solution

  • It's not clear to me, what you're trying to do with AnimatedView, so I won't be able to give you a real solution on how it would be working correctly, only on what's your issue here. If this is your full implementation, you should maybe try to implement the behavior it in your activity itself.

    In your posted Runnable you inflate your layout from XML. That means you create new layouts and views and assign these to your local variable. These views are not part of the layout hierarchy displayed in your activity. So when you update the text of the TextView you'll never see any changes anywhere.

    As a sidenote: Use postDelayed(Runnable, long) instead of creating a new Thread.