Hot questions for Using Butter Knife in textview

Question:

We are using android sdk 26 with butterknife 8.8.1

The HomeActivity has a navigation header, the navigation header also contains some text view. Is it possible to bind the TextViews in HomeActivity ?!

Here are some codes which describes my problem

The HomeActivity class has below layout

<android.support.v4.widget.DrawerLayout ....

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        .....
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/activity_navigation_drawer" />



</android.support.v4.widget.DrawerLayout>

The nav_header has some TextView in it

<LinearLayout ....

    <TextView
        android:id="@+id/userinfo_vo_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView" />


</LinearLayout>

Is it possible to bind the id of userinfo_vo_name text view in HomeActivity, the simple BindView fails

//fails 
@BindView(R.id.userinfo_vo_name)
TextView userinfoName;

Of course, I have called ButterKnife.bind(this); in onCreate method, but it seems not enough.


Answer:

Try this

NavigationView navigationView = (NavigationView) findViewById(R.id.yournavigationView);        
tvProfileName = (TextView) navigationView.getHeaderView(0).findViewById(R.id.tv_nav_userName);
imgUserProfile = (ImageView) navigationView.getHeaderView(0).findViewById(R.id.profile_image);

Question:

I have more than one textview and I want to add text to textview dynamically using Butter knife library. I have done this thing from my side in my code but I want to know any other good way to do same thing.

    public class MainActivity extends AppCompatActivity {

    @BindViews({ R.id.tv1, R.id.tv2})
    List<TextView> listTextView;  

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

        // must define this otherwise null pointer error show.
        ButterKnife.bind(MainActivity.this);

        listTextView.get(0).setText("First TextView ");
        listTextView.get(1).setText("Second TextView ");
    }
}

Answer:

You can store the text content in another array say textTitles and then use Butterknife's Action interface to set the text of each of the text view

static final ButterKnife.Action<TextView> SET_TEXT = new ButterKnife.Action<TextView>() {
   @Override 
   public void apply(TextView view, int index) {
       view.setText(textTitles[index]);
   }
};

and then finally call

ButterKnife.apply(listTextView, SET_TEXT);

Question:

I'm a little bit new using Butterknife and I'm having a problem. I want click on a textview and the open another activity. I know how to do that without using Butterknife, but this is what I did so far:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    ButterKnife.bind(this);


}

@OnClick(R.id.tv_forgot_pass)
void forgotPassClick(){
        Context mContext = LoginActivity.this;
        Class nextActivity = ForgotPasswordActivity.class;
        Intent mIntent = new Intent(mContext, nextActivity);
        startActivity(mIntent);
        finish();
    }
}

My problem right now is I don't know how to use my onClick method, because if I put the that method inside the onCreate, the activity will open the next activity immediately. I tried to use tv_forgot_pass.setOnClickListener and didn't work. And also doesn't work in the xml because the method doesnt have a View as parameter.

It is okey what Im doing? or there is another way to set a clicklistner with Butterknife?

I'm going to explain why is not duplicated with this question

First, they are using and old version of Butterknife, I'm using the 8.8.1 version and the "duplicate question" is using 6.1.0. My version doesnt support InjectView(it's Bind now). Second, my question talks about click on a TextView, the other question talks about click on a button. It's similar but not the equal. And the most important, I read the "duplicate question" like an hour ago, before I asked my question and because I didn't find a solution to my problem I decided to post my question.


Answer:

java.lang.IllegalStateException: Could not find method forgotPassClick(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.support.v7.widget.AppCompatTextView with id 'tv_forgot_pass'

Logcat showing IllegalStateException

Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.

  • You should Use AppCompatTextView instead of TextView.
  • Remove android:onClick="forgotPassClick" from XML.

XML

<android.support.v7.widget.AppCompatTextView 
    android:id="@+id/tv_forgot_pass"  
    android:focusable="true" 
    .... />

Then

@OnClick(R.id.tv_forgot_pass)
void forgotPassClick(){
        Context mContext = LoginActivity.this;
        Intent mIntent = new Intent(mContext, ForgotPasswordActivity.class);
        startActivity(mIntent);
        finish();
    }
}

Question:

I have never used butterknife before. Instead of using the repeated findViewById(...) in my project, I want to use that library instead. However I get an exception.

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
                                                                                            at popularmovies.theo.tziomakas.popularmovies.DetailsFragment$1.onResponse(DetailsFragment.java:224)

Here is my class.

public class DetailsFragment extends Fragment implements
                LoaderManager.LoaderCallbacks<Object>,
                TrailersAdapter.TrailersAdapterOnClickHandler{
            private static final int TRAILERS_LOADER_ID = 0;
            private static final int REVIEWS_LOADER_ID =   1;

            private static final String TRAILERS_LAYOUT = "DetailsFragment.trailer.layout";
            private static final String REVIEWS_LAYOUT = "DetailsFragment.review.layout";

            int recyclerViewOrientation = LinearLayoutManager.VERTICAL;

            private static final String TRAILERS_LIST = "trailers_list";
            private static final String REVIEWS_LIST = "reviews_list";
            /*****************************************************
             * Lists where fetched trailers and reviews are stored.
             *****************************************************/
            private List<Trailers> trailersList = new ArrayList<>();
            private List<Reviews> reviewsList = new ArrayList<>();

            private static final String[] FAVOURITE_MOVIE_PROJECTION = {
                    FavouriteContract.FavouriteEntry.COLUMN_MOVIE_ID,
                    FavouriteContract.FavouriteEntry.COLUMN_MOVIE_POSTER_PATH,
                    FavouriteContract.FavouriteEntry.COLUMN_MOVIE_TITLE,
                    FavouriteContract.FavouriteEntry.COLUMN_MOVIE_OVERVIEW,
                    FavouriteContract.FavouriteEntry.COLUMN_MOVIE_VOTE_AVERAGE,
                    FavouriteContract.FavouriteEntry.COLUMN_MOVIE_RELEASE_DATE
            };

            /**************************************************************************
             * Those custom adapter will actually send the views to the recycler views.
             **************************************************************************/
            private  TrailersAdapter trailersAdapter;
            private  ReviewsAdapter reviewsAdapter;

            /*******************************************
             * RecyclerViews that will display our data.
             *******************************************/
            private  RecyclerView trailersRecyclerView;
            private  RecyclerView reviewsRecyclerView;


            private static final String MOVIE_SHARE_HASHTAG = " #PopularMoviesApp";
            private static final String LOG_TAG = "DetailsFragment";

            private Cursor favoriteCursor;
            private String mMovieId;
            private String mImage;
            private String mTitle;
            private double mRating;
            private String mDate;
            private String mOverview;
            private String oldReviewText;

            @BindView(R.id.no_reviews_text_view)
            public TextView noReviewTextView;

            @BindView(R.id.no_trailers_text_view)
            public TextView noTrailersTextView;

            @BindView(R.id.movie_image)
            public ImageView i;

            @BindView(R.id.movie_title)
            public TextView t;

            @BindView(R.id.movie_rating)
            public TextView r;

            @BindView(R.id.movie_date)
            public TextView d;

            @BindView(R.id.movie_overview)
            public TextView o;
            ...
            ButterKnife.bind(getActivity());
             Call<Movies> call = apiService.getMovieDetails(mMovieId, BuildConfig.MOVIESDB_API_KEY);
    call.enqueue(new Callback<Movies>() {
        @Override
        public void onResponse(Call<Movies> call, Response<Movies> response) {
            Movies movie = response.body();
            mImage = movie.getImageThumbnail();
            mTitle = movie.getTitle();
            mOverview = movie.getOverview();
            mRating = movie.getRating();
            mDate = movie.getDate();

            Picasso.with(getContext()).load(NetworkUtils.IMAGE_URL + NetworkUtils.IMAGE_SIZE_185 + mImage).into(i);
            //I get the error here. 
            t.setText(mTitle);
            o.setText(mOverview);
            r.setText(String.valueOf(mRating));
            d.setText(mDate);

        }

        @Override
        public void onFailure(Call<Movies> call, Throwable t) {
            // Log error here since request failed
            Log.e(LOG_TAG, t.toString());
        }
    });

Any ideas?

Thanks,

Theo


Answer:

You need to call ButterKnife.bind() inside of a method, you can't call it outside the method. And for fragment, you need to call it inside onCreateView():

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  View view = inflater.inflate(R.layout.fancy_fragment, container, false);
  ButterKnife.bind(this, view);
  // TODO Use fields...
  return view;
}

Please read the documentation at http://jakewharton.github.io/butterknife/