android.view.InflateException:二进制 XML 文件第 9 行:使用 Android API 19 膨胀 class android.support.v7.widget.CardView 时出错

android.view.InflateException: Binary XML file line #9: Error inflating class android.support.v7.widget.CardView with Android API 19

我知道这是一个非常常见的问题,我四处寻找解决方案,但到目前为止没有任何帮助。

我收到此异常仅在 API 级别 19(我的 minSDKVersion 是 19,编译和 targetSDK 版本是 25)

我已经尝试使用模拟器 运行 达到 API 级别并且一切正常。

API level 25 - works
API level 23 - works
API level 22 - works
API level 21 - works
API level 19 - crashes with following exception

以下是例外情况:

android.view.InflateException: Binary XML file line #9: Error inflating class android.support.v7.widget.CardView
at android.view.LayoutInflater.createView(LayoutInflater.java:621)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:697)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:756)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at com.nitinsharma.materiallistview.CardRecycleViewAdapter.onCreateViewHolder(CardRecycleViewAdapter.java:21)
at com.nitinsharma.materiallistview.CardRecycleViewAdapter.onCreateViewHolder(CardRecycleViewAdapter.java:15)
at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6290)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5478)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5363)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5359)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2141)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1525)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1488)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:585)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3506)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3254)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3767)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1055)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:437)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:14817)
at android.view.ViewGroup.layout(ViewGroup.java:4631)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1987)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1744)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
at android.view.Choreographer.doCallbacks(Choreographer.java:574)
at android.view.Choreographer.doFrame(Choreographer.java:544)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
    at java.lang.reflect.Method.invokeNati

下面是我的Gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.1"
    defaultConfig {
        applicationId "com.nitinsharma.materiallistview"
        minSdkVersion 19
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
            exclude group: 'com.android.support', module: 'support-annotations'
        })
        testCompile 'junit:junit:4.12'


        compile 'com.android.support:cardview-v7:25.+'
        compile 'com.android.support:appcompat-v7:25.+'
        compile 'com.android.support:recyclerview-v7:25.+'
        compile 'com.android.support:cardview-v7:25.+'
        compile 'com.android.support:gridlayout-v7:25.+'
        compile 'com.android.support:support-v4:25.+'
        compile 'com.android.support:design:25.+'
    }

}

最后是我的 card_view.xml 文件:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"

    xmlns:android="http://schemas.android.com/apk/res/android">

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/bottomcardview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    card_view:cardBackgroundColor="@android:color/transparent"
    card_view:cardElevation="-1dp"
    >


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <android.support.v7.widget.CardView
        android:id="@+id/topcardview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        card_view:cardBackgroundColor="@android:color/white"
        card_view:cardUseCompatPadding="true"
        card_view:cardElevation="6dp"
        card_view:cardCornerRadius="4dp"
        android:transitionName="content"

        >

        <ImageView
            android:id="@+id/cardImage"
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:layout_gravity="left"
            android:transitionName="image"
            />
        <ImageView
            android:id="@+id/arrow"
            android:layout_width="50dp"
            android:layout_height="match_parent"
            android:layout_gravity="right|bottom"/>
        <TextView
            android:id="@+id/cardtext"
            android:layout_gravity="top|left"
            android:layout_marginLeft="110dp"
            android:textColor="#000"
            android:textSize="22sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:shadowColor="@android:color/black"
            android:fontFamily="sans-serif"
            android:elevation="4dp"
            android:textStyle="normal|bold"
            android:textAllCaps="false" />

        <TextView
            android:id="@+id/cardtextsubs"
            android:text="Hello World"
            android:layout_marginLeft="110dp"
            android:layout_marginRight="50dp"
            android:layout_gravity="bottom"
            android:textColor="#000"
            android:textSize="13sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:shadowColor="@android:color/black"
            android:fontFamily="sans-serif"
            android:elevation="4dp"
            android:textStyle="normal|italic"
            android:textAllCaps="false" />


        <View
            android:id="@+id/dividerLeft"
            android:layout_marginLeft="100dp"
            android:layout_width="2dp"
            android:layout_height="match_parent"
            android:elevation="8dp"
            android:background="?android:attr/listDivider"/>


        </android.support.v7.widget.CardView>


 </RelativeLayout>

</android.support.v7.widget.CardView>

</RelativeLayout>

我收到错误的代码行:

public class CardRecycleViewAdapter extends RecyclerView.Adapter<CardViewHolder> {


    @Override
    public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Log.d("TAG","inside oncreateviewholder");
        **View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view,parent,false);**
        CardViewHolder viewHolder = new CardViewHolder(v,parent);
        return  viewHolder;
    }

我的 jar 文件:

我的主要活动:

public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecycleView;
    private LinearLayoutManager mRecycleViewLayout;
    private RecyclerView.Adapter mRecycleViewAdapter;
    protected static int sizex=0;
    protected static int sizey=0;
    protected static int recycleViewHeight=0;
    protected static RecyclerView sharedRecyclerView;
    protected  static Context mContext;



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


        mRecycleViewLayout = new LinearLayoutManager(this);
        mRecycleViewAdapter = new CardRecycleViewAdapter();
        mRecycleView = (RecyclerView) findViewById(R.id.recycleViewRight);
        mRecycleView.setHasFixedSize(true);
        mRecycleView.setLayoutManager(mRecycleViewLayout);
        mRecycleView.setAdapter(mRecycleViewAdapter);

....
}

那是因为card_view:cardElevation="-1dp"值必须>=0:

  1. CardView方法initialize(Context context, AttributeSet attrs, int defStyleAttr)中,它调用IMPL.initialize(mCardViewDelegate, context, backgroundColor, radius, elevation, maxElevation);
  2. IMPL像这样:

    static {
    if (Build.VERSION.SDK_INT >= 21) {
        IMPL = new CardViewApi21();
    } else if (Build.VERSION.SDK_INT >= 17) {
        IMPL = new CardViewJellybeanMr1();
    } else {
        IMPL = new CardViewGingerbread();
    }
    IMPL.initStatic();
    

    }

  3. 由于API等级低于21,所以CardViewJellybeanMr1被创建;
  4. CardViewJellybeanMr1#initialize中它调用了createBackground-->new RoundRectDrawableWithShadow-->setShadowSize,这里说:

    if (shadowSize < 0f) {
        throw new IllegalArgumentException("Invalid shadow size " + shadowSize +
                ". Must be >= 0");
    }
    

shadowSize等同于cardElevation