Skip to content
This repository has been archived by the owner on Dec 11, 2022. It is now read-only.

How do I access childviews of any layout? I want to change their values programatically. Thanks for building an awesome library. #12

Open
javedk16 opened this issue Apr 22, 2016 · 7 comments

Comments

@javedk16
Copy link

No description provided.

@kunal-jaggi
Copy link

I am also stuck here. I am trying to change the "text" attribute of child view programmatically but it is not working.

@j2esu
Copy link
Owner

j2esu commented May 8, 2016

Hello. If I understand right, the question is how to programmatically acess to JoinableLayout views. So, take a look at Full Demo App onCreateMethod. I use onInflateComplete callback to set on click listeners, like:

rvJoiner.add(new JoinableLayout(R.layout.clickable, new JoinableLayout.Callback() {
            @Override
            public void onInflateComplete(View view, ViewGroup parent) {
                view.findViewById(R.id.clickable_btn).setOnClickListener(AMain.this);
            }
        }));

"View view" param is the root of your JoinableLayout.

@j2esu
Copy link
Owner

j2esu commented May 8, 2016

NOTE: if you're using this method to save links to child views for later changing values (for example, text in TextView), you should be aware of RecyclerView behavior - it can recycle your layout and recreate it later, and all your changes will be lost, so ensure you also bind your current data in onInflateComplete callback

@kunal-jaggi
Copy link

This is a great library. The recycler view library works fine, expect one thing. Consider the following code snippet:

rvJoiner.add(new JoinableLayout(R.layout.movie_details));
rvJoiner.add(new JoinableLayout(R.layout.reviews));

In reviews.xml layout file I have a TextView with hard coded android:text="Reviews". But, in movie_details layout I want to dynamically populate some TextFields. For example, a movie title, release year, ratings etc. I am inflating the details xml and filling the elements from a DB cursor.

        View view = inflater.inflate(R.layout.movie_details, container, false);

        mMovieTileTxt = (TextView) view.findViewById(R.id.movieTitle);
        mMoviePoster =  (ImageView) view.findViewById(R.id.moviePoster);

And, then I pull values from a cursor and try to fill the views (using setText etc. APIs). But, this is not working. In the logs, I can see that cursor has the correct value but setText API does not change the text of a TextView.

@j2esu
Copy link
Owner

j2esu commented May 8, 2016

Of course, the view you've inflated are not displayed on the screen, because you've not added it. RvJoiner inflates your layout itself, and you should use inflate callback to find your text views, as i wrote in previous comment:

rvJoiner.add(new JoinableLayout(R.layout.movie_details, new JoinableLayout.Callback() {
            @Override
            public void onInflateComplete(View view, ViewGroup parent) {
                mMovieTileTxt = (TextView) view.findViewById(R.id.movieTitle);
                mMoviePoster =  (ImageView) view.findViewById(R.id.moviePoster);
            }
        }));

@kunal-jaggi
Copy link

kunal-jaggi commented May 8, 2016

Thanks. But I noticed something weird. The onInflateComplete callback is randomly triggered. The following code snippet shows how I am adding and getting references inside the onInflateComplete callback.


        rvJoiner.add(new JoinableLayout(R.layout.movie_details, new JoinableLayout.Callback() {
            @Override
            public void onInflateComplete(View view, ViewGroup parent) {
                mMovieTileTxt = (TextView) view.findViewById(R.id.movieTitle);
                mMoviePoster =  (ImageView) view.findViewById(R.id.moviePoster);
                mMovieReleaseYear =  (TextView) view.findViewById(R.id.movieReleaseYear);
                mMovieRating =  (TextView) view.findViewById(R.id.movieRating);
                mMovieOverview =  (TextView) view.findViewById(R.id.movieOverview);
                mMovieFavorite =  (ImageView) view.findViewById(R.id.favoriteIcon);
            }
        }));

And then later in my code I try to set the value of TextView using setText(string) API. I ran the app, it crashed and I got a NullPointerException. The OS killed the app. I restarted the app and again got a NPE. The third time, it worked. So, on first two launches the callback wasn't triggered and the objects were null.

@j2esu
Copy link
Owner

j2esu commented May 9, 2016

To be used in RecyclerView, my lib wraps your layout into RecyclerView.Adapter. This callback is called after RecyclerView.Adapter.onCreateViewHolder. It can be called at any time (in our case, at first time) when you scroll list and your layout became visible. So, you can you setText only after this callback. Moreover,

NOTE: if you're using this method to save links to child views for later changing values (for example, text in TextView), you should be aware of RecyclerView behavior - it can recycle your layout and recreate it later, and all your changes will be lost, so ensure you also bind your current data in onInflateComplete callback

It seems you not clearly understand what happens inside of RecyclerView. This video can be useful. Good luck in your projects! :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants