Search code examples
androidnullpointerexceptionandroid-design-libraryandroid-textinputlayout

TextInputLayout (TextInputEditText) NullpointerException when click the toggle button


I'm using TextInputLayout (and TextInputEditText) for the password field, but my app it's breaking when I'm pressing the toggle button on my tablet.

I tested on another devices an the app work like a charm Here's some information:

Worked on
- Nexus 5 - 6.0.1
- Positivo S440 - 4.4.2
- Samsung Galaxy Tab SM-P550 - 6.0.1

Crashed on
- Tablet: Samsung SM-T530
- Android: 5.0.2
- Android Support Design Version: 25.3.1

My XML


android.support.design.widget.TextInputLayout
    android:id="@+id/til_password"
    style="@style/Text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:layout_marginLeft="16dp"
    android:layout_marginStart="16dp"
    android:hint="@string/lbl_password"
    app:passwordToggleEnabled="true"
    app:passwordToggleTint="@color/theme_accent"

    android.support.design.widget.TextInputEditText
        android:id="@+id/inp_password"
        style="@style/Text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@null"
        android:imeOptions="actionDone"
        android:inputType="textPassword"
        android:textColor="@color/theme_accent"
        android:textSize="@dimen/text_size_subhead"

android.support.design.widget.TextInputLayout

My code


public class SyncFragment extends GenericFragment implements TaskCallback,
        View.OnClickListener, WifiAdapter.WifiListener, BackIntercepter, TextView.OnEditorActionListener {

    private TextInputEditText mInpPassword;

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.layout_sync, container, false);
        ButterKnife.bind(this, view);
        findViews(view);

        if (getArguments() != null) {
            List wifis = getArguments().getParcelableArrayList(Extras.WIFIS);
            if(wifis != null) {
                Log.d("HACL.TEST", "content extra info: " + Extras.WIFIS);
                Log.d("HACL.TEST", "content wifis: " + wifis.toString());
                updateSpinner(wifis);
                networkId = getArguments().getInt(Extras.NETWORK_ID);
                airConWifiSSID = getArguments().getString(Extras.AIR_CON_WIFI);
            }
        }

        setListeners();
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        try {
            // If return from SyncingFragment, load which Wi-Fi network was selected and show
            // credential screen instead of Wi-Fi list screen
            if(getArguments().getBoolean(Extras.BACK_FROM_SYNCING)) {
                if (getArguments().getParcelable(Extras.WIFI) != null) {
                    Wifi wifi = getArguments().getParcelable(Extras.WIFI);
                    mOutNetwork.setText(wifi.getSsid());
                    mOutNetwork.setTextColor(getResources().getColor(R.color.theme_accent));
                    mOutNetwork.setAlpha(1);
                    mOutNetwork.setTag(wifi);
                    Typeface face = Typeface.createFromAsset(getContext().getAssets(), "fonts/FonteX-Regular.ttf");
                    mOutNetwork.setTypeface(face);
                    mInpPassword.setTypeface(face);
                }
                showCredentials();
            }
            else {
                showList();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void findViews(View view) {
        Typeface face = Typeface.createFromAsset(getContext().getAssets(),"fonts/FontX-Regular.ttf");

        mInpPassword = (TextInputEditText) view.findViewById(R.id.inp_password);
        mInpPassword.setTypeface(face);

        .....
    }

    private void finishSync() {

        if (mOutNetwork.getTag() == null) {
            Toast.makeText(getActivity(), R.string.msg_select_an_network, Toast.LENGTH_SHORT).show();
            return;
        }

        String password = mInpPassword.getText().toString();
        if (verifyPassword(password)) {
            Wifi wifi = (Wifi) mOutNetwork.getTag();
            wifi.setPassphrase(password);

            Bundle bundle = new Bundle();
            bundle.putParcelable(Extras.WIFI, wifi);
            bundle.putParcelableArrayList(Extras.WIFIS, new ArrayList(wifiOnSpinner));
            bundle.putInt(Extras.NETWORK_ID, networkId);
            bundle.putString(Extras.AIR_CON_WIFI, airConWifiSSID);
            getGenericActivity().openMainFragment(SyncingFragment.class, bundle);
        } else {
            Toast.makeText(getActivity(), R.string.msg_password_invalid, Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onClick(View v) {
        if (v.equals(mLyNetwork)) {
            try {
                CommonUtils.hideInputKeyboard(getActivity());
            } catch (RuntimeException ignored) {

            }
            showList();
        }

        if (v.equals(mBtnSync)) {
            finishSync();
        }
    }

    @Override
    public void onWifiSelected(Wifi wifi) {
        mOutNetwork.setText(wifi.getSsid());
        mOutNetwork.setTextColor(getResources().getColor(R.color.theme_accent));
        mOutNetwork.setAlpha(1);
        mOutNetwork.setTag(wifi);
        Typeface face = Typeface.createFromAsset(getContext().getAssets(),"fonts/ElectroluxSans-Regular.ttf");
        mOutNetwork.setTypeface(face);
        mInpPassword.setTypeface(face);

        if (wifi.getSecurityType() > 0) {
            showCredentials();
        } else {
            finishSync();
        }
    }

    @Override
    public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
        Wifi tag = (Wifi) mOutNetwork.getTag();
        // If Wi-Fi network has some security type, minimum password length is:
        // For a 64 bit WEP network the password is 5-characters.
        // For a 128 bit WEP network the password is 13-characters.
        // WPA uses either a passphrase (a shared secret) that is comprised of 8 to 63 characters
        if (textView.getText() != null
                && textView.getText().length()  0) {
            mBtnSync.setEnabled(false);
        } else {
            mBtnSync.setEnabled(true);
        }

        if (i == EditorInfo.IME_ACTION_DONE && mBtnSync.isEnabled()) {
            finishSync();
            return true;
        }
        return false;
    }
    public void showCredentials() {
        int duration = getResources().getInteger(android.R.integer.config_mediumAnimTime);
        lyCredentials.setVisibility(View.VISIBLE);
        ViewCompat.animate(listNetwork).alpha(0f)
                .setInterpolator(new DecelerateInterpolator())
                .setDuration(duration)
                .setListener(new ViewPropertyAnimatorListenerAdapter() {

                    @Override
                    public void onAnimationEnd(View view) {
                        listNetwork.setVisibility(View.GONE);
                    }

                })
                .start();
        ViewCompat.animate(lyCredentials).alpha(1f)
                .setStartDelay(duration)
                .setInterpolator(new DecelerateInterpolator())
                .setListener(new ViewPropertyAnimatorListenerAdapter() {

                    @Override
                    public void onAnimationEnd(View view) {
                        mInpPassword.requestFocus();
                        CommonUtils.showInputKeyboard(getActivity(), mInpPassword);
                    }

                })
                .setDuration(duration)
                .start();

        mBtnSync.setEnabled(false);
    }

    @Override
    public void onWifiSelected(Wifi wifi) {
        mOutNetwork.setText(wifi.getSsid());
        mOutNetwork.setTextColor(getResources().getColor(R.color.theme_accent));
        mOutNetwork.setAlpha(1);
        mOutNetwork.setTag(wifi);
        Typeface face = Typeface.createFromAsset(getContext().getAssets(),"fonts/FontX-Regular.ttf");
        mOutNetwork.setTypeface(face);
        mInpPassword.setTypeface(face);

        if (wifi.getSecurityType() > 0) {
            showCredentials();
        } else {
            finishSync();
        }
    }
    private void setListeners() {
        mLyNetwork.setOnClickListener(this);
        mInpPassword.setOnEditorActionListener(this);
        mBtnSync.setOnClickListener(this);
    }
}

And here is the logcat


05-15 09:22:31.199 20164-20164/com.xxxxxxx.yyyyyyyy.zzzz E/AndroidRuntime: FATAL EXCEPTION: 
main
Process: com.xxxxxxxx.yyyyyyyyy.zzzzz, PID: 20164
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
at android.graphics.drawable.AnimatedVectorDrawable.start(AnimatedVectorDrawable.java:423)
at android.graphics.drawable.AnimatedStateListDrawable$AnimatedVectorDrawableTransition.start(AnimatedStateListDrawable.java:322)
at android.graphics.drawable.AnimatedStateListDrawable.selectTransition(AnimatedStateListDrawable.java:226)
at android.graphics.drawable.AnimatedStateListDrawable.onStateChange(AnimatedStateListDrawable.java:153)
at android.graphics.drawable.Drawable.setState(Drawable.java:644)
at android.support.v4.graphics.drawable.DrawableWrapperGingerbread.setState(DrawableWrapperGingerbread.java:145)
at android.support.v4.graphics.drawable.DrawableWrapperLollipop.setState(DrawableWrapperLollipop.java:95)
at android.widget.ImageView.drawableStateChanged(ImageView.java:1129)
at android.support.v7.widget.AppCompatImageButton.drawableStateChanged(AppCompatImageButton.java:149)
at android.view.View.refreshDrawableState(View.java:17099)
at android.support.design.widget.CheckableImageButton.setChecked(CheckableImageButton.java:75)
at android.support.design.widget.TextInputLayout.passwordVisibilityToggleRequested(TextInputLayout.java:1302)
at android.support.design.widget.TextInputLayout$4.onClick(TextInputLayout.java:1076)
at android.view.View.performClick(View.java:5214)
at android.view.View$PerformClick.run(View.java:20978)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6134)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

As you can see, the problem is in the android support design library

I found this link below and we have more developers with the same problem.
Google Issue Tracker: Error Support Design

If anyone knows some workaround or solution, please tell us.


Solution

  • {
        //...
        EditText et;
        //...
        //left, top, right, bottom
        et.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.some_icon, 0);
        et.setOnTouchListener(someTouchListener);
        //...
    }
    
    private View.OnTouchListener someTouchListener = new OnTouchListener() {
        final int DRAWABLE_LEFT = 0;
        final int DRAWABLE_TOP = 1;
        final int DRAWABLE_RIGHT = 2;
        final int DRAWABLE_BOTTOM = 3;
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                if (event.getRawX() >= (v.getRight() - ((EditText) v).getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
                   //TODO Drawable click here 
                    return true;
                }
            }
            return false;
        }
    };