无法使用其中的 appcompat 元素创建自定义数组适配器

Can't create custom arrayadapter with appcompat elements inside of it

我制作了一个扩展 ArrayAdapter 的适配器以创建自定义项目列表。这些项目有一个可绘制对象、一个文本视图,最后是一个 AppCompatCheckBox

不幸的是 AppCompatCheckBox 组件没有得到渲染。当我将 AppCompatCheckBox 更改为 CheckBox 时,效果很好。我在我的 activity 的另一部分添加了一个 AppCompatCheckBox,它工作得很好,只有当它在适配器中时才是问题。

下面的代码示例:

自定义项:

import android.graphics.drawable.Drawable;

public class PackageListItem {

    private Boolean enabledState;
    private String packageName;
    private Drawable packageIcon;

    public PackageListItem(Boolean enabledState, String packageName, Drawable packageIcon){
        this.enabledState = enabledState;
        this.packageName = packageName;
        this.packageIcon = packageIcon;
    }

    public boolean getPackageEnabled(){
        return enabledState;
    }

    public Drawable getPackageIcon(){
        return packageIcon;
    }

    public String getPackageName(){
        return packageName;
    }

    public void setPackageEnabled(Boolean enabledState){
        this.enabledState = enabledState;
    }

    public void setPackageIcon(Drawable packageIcon){
        this.packageIcon = packageIcon;
    }

    public void setPackageName(String packageName){
        this.packageName = packageName;
    }
}

自定义适配器:

import android.content.Context;
import android.support.v7.widget.AppCompatCheckBox;
import android.support.v7.widget.SwitchCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.Switch;
import android.widget.TextView;

import java.util.ArrayList;


public class PackageListAdapter extends ArrayAdapter<PackageListItem> {


    public PackageListAdapter(Context context, ArrayList<PackageListItem> packages){
        super(context, 0, packages);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        PackageListItem packageItem = getItem(position);

        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.package_item, parent, false);
        }

        TextView tvPackageName = (TextView) convertView.findViewById(R.id.packageName);
        ImageView ivPackageIcon = (ImageView) convertView.findViewById(R.id.packageIcon);
        CheckBox sPackageSwitch = (CheckBox) convertView.findViewById(R.id.packageEnabled);

        tvPackageName.setText(packageItem.getPackageName());
        ivPackageIcon.setImageDrawable(packageItem.getPackageIcon());
        sPackageSwitch.setChecked(packageItem.getPackageEnabled());

        return convertView;
    }
}

自定义项目XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1">
        <ImageView
            android:id="@+id/packageIcon"
            android:layout_width="40dp"
            android:layout_height="40dp" />
        <TextView
            android:id="@+id/packageName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            style="@style/AppTheme.ListTitle"/>
    </LinearLayout>
    <CheckBox
        android:id="@+id/packageEnabled"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

我正在初始化列表:

 private void initPackagesList(){
        ArrayList<PackageListItem> arrayListOfPackages = new ArrayList<>();

        PackageManager pm = getPackageManager();
        List<ResolveInfo> apps = pm.queryIntentActivities(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER), 0);

        for(ResolveInfo apInfo : apps){
            String packageName = apInfo.loadLabel(pm).toString();
            Drawable packageIcon = apInfo.loadIcon(pm);
            boolean packageState = myPreferences.getBoolean(packageName, false);

            Log.d("MainActivity","" + packageName);

            PackageListItem item = new PackageListItem(packageState, packageName, packageIcon);

            arrayListOfPackages.add(item);
        }

        PackageListAdapter adapter = new PackageListAdapter(getApplicationContext(),arrayListOfPackages);
        ListView listView = (ListView) findViewById(R.id.packages_listview);
        listView.setAdapter(adapter);
    }

结果:

您的问题在于您初始化适配器的方式。

要解决您的问题,请将 new PackageListAdapter(getApplicationContext(),arrayListOfPackages); 替换为 new PackageListAdapter(this,arrayListOfPackages);。 (或 getActivity() 如果在片段内)。

如果我错了请纠正我,但我相信 AppCompat 库依赖于 ContextWrapper to style most views. Using getApplicationContext() passes, well, the base application context to your ListView adapter and thus bypasses the AppCompat ContextWrapper. Passing this or getActivity() passes the top AppCompatActivity 可以告诉 LayoutInflators 应用其他样式的上下文。没有它,您的适配器的 LayoutInflater 将使用默认样式。

当然,你的 activity 也应该扩展 AppCompatActivity 但我认为你已经知道了。