8

I am using TextInputLayout wrapped around a EditText for a RecyclerView item. I am using style "Theme.AppCompat.Light.NoActionBar". But still I get the error "Caused by: java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.AppCompat (or a descendant)." However when I remove the TextInputLayout from the xml, the App runs fine.

Here is my RecyclerView item (item_content_settings):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:weightSum="20">

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="18"
        android:padding="16dp">

        <EditText
            android:id="@+id/content_summary"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:hint="First Name"
            android:inputType="text"
            android:text="First Name And Last Name" />

    </com.google.android.material.textfield.TextInputLayout>

    <ImageView
        android:id="@+id/pencil"
        android:layout_width="0dp"
        android:layout_height="16dp"
        android:layout_gravity="center"
        android:layout_margin="0dp"
        android:layout_weight="2"
        android:src="@drawable/pencil_edit" />
</LinearLayout>

My Style:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="AppTheme.Base">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>

    <!--    <style name="AppTheme.NoActionBar">-->
    <!--        <item name="windowActionBar">false</item>-->
    <!--        <item name="windowNoTitle">true</item>-->
    <!--    </style>-->

    <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
        <item name="android:windowBackground">@drawable/background</item>
    </style>


    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

</resources>

AndroidManifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.sed.RP">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:name=".MainApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
            android:name=".SplashActivity"
            android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme"></activity>

        <activity android:name=".WelcomeActivity" />
        <activity android:name=".LoginActivity" />
        <activity android:name=".SignupActivity" />
        <activity android:name=".ForgotPasswordActivity" />
        <activity android:name=".VerifyEmailActivity" />

    </application>

</manifest>

error:

2019-09-19 14:20:31.276 30912-30912/com.sed.RP E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.sed.RP, PID: 30912
    android.view.InflateException: Binary XML file line #8: Binary XML file line #8: Error inflating class <unknown>
    Caused by: android.view.InflateException: Binary XML file line #8: Error inflating class <unknown>
    Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
        at android.view.LayoutInflater.createView(LayoutInflater.java:652)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:812)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:752)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:883)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:846)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:522)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:430)
        at com.sed.RP.SettingsAdapter.onCreateViewHolder(SettingsAdapter.java:46)
        at com.sed.RP.SettingsAdapter.onCreateViewHolder(SettingsAdapter.java:23)
        at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6794)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5975)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3641)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4194)
        at android.view.View.layout(View.java:17666)
        at android.view.ViewGroup.layout(ViewGroup.java:5577)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
        at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1730)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1496)
        at android.view.View.layout(View.java:17666)
        at android.view.ViewGroup.layout(ViewGroup.java:5577)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:17666)
        at android.view.ViewGroup.layout(ViewGroup.java:5577)
        at com.google.android.material.appbar.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:142)
        at com.google.android.material.appbar.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:41)
        at com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1556)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:888)
        at android.view.View.layout(View.java:17666)
        at android.view.ViewGroup.layout(ViewGroup.java:5577)
        at androidx.drawerlayout.widget.DrawerLayout.onLayout(DrawerLayout.java:1231)
        at android.view.View.layout(View.java:17666)
        at android.view.ViewGroup.layout(ViewGroup.java:5577)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:17666)
        at android.view.ViewGroup.layout(ViewGroup.java:5577)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
        at android.view.View.layout(View.java:17666)
        at android.view.ViewGroup.layout(ViewGroup.java:5577)
2019-09-19 14:20:31.277 30912-30912/com.sed.RP E/AndroidRuntime:     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:17666)
        at android.view.ViewGroup.layout(ViewGroup.java:5577)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
        at android.view.View.layout(View.java:17666)
        at android.view.ViewGroup.layout(ViewGroup.java:5577)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:730)
        at android.view.View.layout(View.java:17666)
        at android.view.ViewGroup.layout(ViewGroup.java:5577)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2394)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2116)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1302)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6441)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:876)
        at android.view.Choreographer.doCallbacks(Choreographer.java:688)
        at android.view.Choreographer.doFrame(Choreographer.java:623)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:862)
        at android.os.Handler.handleCallback(Handler.java:754)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:163)
        at android.app.ActivityThread.main(ActivityThread.java:6238)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:933)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
     Caused by: java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
        at com.google.android.material.internal.ThemeEnforcement.checkTheme(ThemeEnforcement.java:221)
        at com.google.android.material.internal.ThemeEnforcement.checkAppCompatTheme(ThemeEnforcement.java:196)
        at com.google.android.material.internal.ThemeEnforcement.checkCompatibleTheme(ThemeEnforcement.java:131)
        at com.google.android.material.internal.ThemeEnforcement.obtainTintedStyledAttributes(ThemeEnforcement.java:110)
        at com.google.android.material.textfield.TextInputLayout.<init>(TextInputLayout.java:266)
        at com.google.android.material.textfield.TextInputLayout.<init>(TextInputLayout.java:247)
            ... 80 more

RecyclerAdapter:

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

import butterknife.BindView;
import butterknife.ButterKnife;
import ca.barrenechea.widget.recyclerview.decoration.StickyHeaderAdapter;

public class SettingsAdapter extends RecyclerView.Adapter<SettingsAdapter.MyViewHolder>
        implements StickyHeaderAdapter<SettingsAdapter.HeaderHolder> {

    private LayoutInflater inflater;
    private ArrayList<SettingsItem> items;
    private ClickListener clickListener;
    private SharedPreferences preferences;
    int count;
    private int yearInfoPos;


    public SettingsAdapter(Context context, ArrayList<SettingsItem> items, int count, int yearInfoPos) {
        inflater = LayoutInflater.from(context);
        this.items = items;
        this.count = count;
        this.yearInfoPos = yearInfoPos;
        preferences = PreferenceManager.getDefaultSharedPreferences(context);
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View view = inflater.inflate(R.layout.item_content_settings, parent, false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {

//        switch (position) {
//            case 0:
//                holder.contentSummary.setHint("First Name");
//                break;
//            case 1:
//                holder.contentSummary.setHint("Last Name");
//                break;
//            case 2:
//                holder.contentSummary.setHint("Email Address");
//                break;
//            case 3:
//                holder.contentSummary.setHint("Password");
//                break;
//        }
        holder.contentSummary.setHint(items.get(position).title);
        holder.contentSummary.setText(items.get(position).contentSummary);
    }

    @Override
    public int getItemCount() {
        return count;
    }

    public void setClickListener(ClickListener clickListener) {
        this.clickListener = clickListener;
    }

    @Override
    public long getHeaderId(int position) {

        if (position < 0) {
            return 0;
        } else if (position < 4) {
            return 4;
        } else if (position < yearInfoPos) {
            return yearInfoPos;
        } else if (position < (yearInfoPos + 2)) {
            return yearInfoPos + 2;
        } else {
            return count - 1;
        }

    }

    @Override
    public HeaderHolder onCreateHeaderViewHolder(ViewGroup parent) {
        final View view = inflater.inflate(R.layout.item_header_settings, parent, false);
        return new HeaderHolder(view);
    }

    @Override
    public void onBindHeaderViewHolder(HeaderHolder headerHolder, int position) {
        if (position < 0) {
            headerHolder.headerText.setText(R.string.settings_title1);
        } else if (position < 4) {
            headerHolder.headerText.setText(R.string.settings_title2);
        } else if (position < yearInfoPos) {
            headerHolder.headerText.setText(R.string.settings_title3);
        } else if (position < (yearInfoPos + 2)) {
            headerHolder.headerText.setText(R.string.settings_title4);
        } else {
            headerHolder.headerText.setText(R.string.settings_title5);
        }

    }

    public interface ClickListener {
        void itemClicked(int position);
    }

    class MyViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.content_summary)
        EditText contentSummary;
        @BindView(R.id.pencil)
        ImageView pencilEdit;

        public MyViewHolder(View itemView) {
            super(itemView);
            //contentSummary = itemView.findViewById(R.id.content_summary);
            ButterKnife.bind(this, itemView);

            pencilEdit.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (clickListener != null) {
                        clickListener.itemClicked(getLayoutPosition());
                    }
                }
            });
        }
    }

    static class HeaderHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.text_header)
        TextView headerText;
        @BindView(R.id.image_header)
        ImageView headerImage;

        public HeaderHolder(View itemView) {
            super(itemView);

            ButterKnife.bind(this, itemView);
//            headerText = itemView.findViewById(R.id.text_header);
//            headerImage = itemView.findViewById(R.id.image_header);
        }
    }

    class AddItemHolder extends RecyclerView.ViewHolder {

        TextView addItem;

        public AddItemHolder(View itemView) {
            super(itemView);
            addItem = itemView.findViewById(R.id.add_item);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (clickListener != null) {
                        clickListener.itemClicked(getLayoutPosition());
                    }
                }
            });
        }
    }
}

Any thoughts? Thanks.

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
itabdullah
  • 605
  • 1
  • 8
  • 22
  • Are you passing a `Context` to your `RecyclerView.Adapter` for the `LayoutInflater`? If so, which `Context`, exactly? – Mike M. Sep 19 '19 at 09:05
  • Refer note from my answer here : https://stackoverflow.com/a/52401497/10271334 – Jeel Vankhede Sep 19 '19 at 09:06
  • OK, what is the first argument in your `new SettingsAdapter(???, ...)` call? – Mike M. Sep 19 '19 at 09:07
  • use material for material textinputLayout instead of normal theme – BlackBlind Sep 19 '19 at 09:08
  • @MikeM., I am passing MainApplication.getInstance() for context. private static MainApplication sInstance; public static MainApplication getInstance() { return sInstance; } – itabdullah Sep 19 '19 at 09:08
  • 4
    You need to pass the `Activity`, not an application `Context`. It won't have a theme set on it. – Mike M. Sep 19 '19 at 09:09
  • 1
    @MikeM., Yes. you are correct. I passed getActivity and now it runs fine. How can I accept your answer? Thanks a lot. – itabdullah Sep 19 '19 at 09:12
  • 1
    No problem. It seems like you're possibly using an older version of Material Components, because the new ones enforce `Theme.MaterialComponents` – as [Gabriele Mariotti alludes to below](https://stackoverflow.com/a/58007618) – rather than `Theme.AppCompat`. Give him a minute, and if he amends his post to address your specific current issue, you can just accept his answer, since it has salient advice for the newer versions, too. Anyhoo, thank you, though. I appreciate the offer. Glad you got it working. Cheers! – Mike M. Sep 19 '19 at 09:23
  • @MikeM. Thanks for the mention. The real issue is the context used as you described in your comment. In any case with the latest version of Material Components he will have another kind of issue. – Gabriele Mariotti Sep 20 '19 at 17:33

3 Answers3

22

As @MikeM. commented on the question there is an issue with the context used to instantiate the Adapter. You need to pass the Activity, not an Application Context.
The ApplicationContext doesn't have your app theme.

But pay attention because you are using the com.google.android.material.textfield.TextInputLayout, check the doc of the Material Components library.
Your app theme should inherit from a Material Components theme.

If you can't change your theme, you can do one of the following:

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • 1
    Gabriele, thanks. I am now using – itabdullah Sep 21 '19 at 05:19
7

If there are components in the activity that use that context, another solution would be to get the Context object, and set its theme to AppCompat. Here's the Kotlin code example:

 val context: Context = getApplicationContext()
 context.setTheme(R.style.your_theme_extending_AppCompatTheme)
 // Use this context throughout the class.
sorry_I_wont
  • 639
  • 1
  • 9
  • 16
2

In my case the problem with TextInputLayout was only in design mode (Android Studio did not show layout). I just changed theme for preview - and everything worked:

Maxim
  • 176
  • 1
  • 3
  • 10