无法在自定义适配器中将 EditText 转换为 TextView

Posted

技术标签:

【中文标题】无法在自定义适配器中将 EditText 转换为 TextView【英文标题】:Cannot cast EditText into TextView in a custom adapter 【发布时间】:2018-02-08 20:06:03 【问题描述】:

我们目前正在进行一个项目,但无法通过这个奇怪的 NullPointerException。我们必须将特定的 EditText 转换为 TextView 才能使我们的 GridView 工作。现在的问题是所有教程似乎都使用 Activity,而我们使用的是 Fragment。我们的“MainActivity”只是在这里初始化一些启动的东西(启动画面、介绍滑块等)。所有其他的东西都发生在我们的“HomeFragment”中。目标是捕获一张图片,写一个标题和一些内容,然后将其保存到 SQLite 数据库中,以后可以使用该数据库在 GridView 中显示它。

我们使用this guys(github) 模板来创建我们自己的数据库(并重写了一些东西,因为我们使用的是片段,当然)。

在阅读代码时请耐心等待,它还没有最终确定。大量的垃圾代码仍然在里面。

FragmentHome.class

public class FragmentHome extends Fragment 

private ImageButton mUnicornButton;
private ImageButton mBaseballbatButton;
private ImageButton mExplosionButton;
private ImageButton mCowButton;
private ImageButton mShitButton;
private ImageButton mPenguinButton;

private final int REQUEST_GALLERY_CODE = 999;

EditText edtTitle, edtContent;
Button btnAdd, btnChoose;

private ImageView mImageView;
protected View mView;

private static final int CAMERA_REQUEST = 1888;

public FragmentHome() 
    // Required empty public constructor


@Override
public void onCreate(Bundle savedInstanceState)
    super.onCreate(savedInstanceState);



public static SQLiteHelper sqLiteHelper;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 
    View v = inflater.inflate(R.layout.fragment_home, container, false);
    this.mView = v;

    initUI(v);
    sqLiteHelper = new SQLiteHelper(getActivity().getApplicationContext(), "ListDB.sqlite",null,1);
    sqLiteHelper.queryData("CREATE TABLE IF NOT EXISTS DBLIST(Id INTEGER PRIMARY KEY AUTOINCREMENT, title VARCHAR, content VARCHAR, image BLOB)");

    btnChoose.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 
            ActivityCompat.requestPermissions(getActivity(),new String[]Manifest.permission.READ_EXTERNAL_STORAGE,REQUEST_GALLERY_CODE);
        
    );
    Button photoButton = v.findViewById(R.id.add_foto);
    photoButton.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 
            Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(cameraIntent, CAMERA_REQUEST);
        
    );
    btnAdd.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 
            try
                sqLiteHelper.insertData(
                        edtTitle.getText().toString().trim(),
                        edtContent.getText().toString().trim(),
                        imageViewToByte(mImageView)
                        );
                Toast.makeText(getActivity().getApplicationContext(),"Added",Toast.LENGTH_SHORT).show();
                edtTitle.setText("");
                edtContent.setText("");
                mImageView.setImageResource(R.mipmap.ic_launcher_round);

             catch(Exception e)
                e.printStackTrace();
            
        
    );



    return v;


private byte[] imageViewToByte(ImageView image) 
    Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG,0,stream);
    byte[] byteArray = stream.toByteArray();
    return byteArray;


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
    if(requestCode == REQUEST_GALLERY_CODE)
        if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setType("image/*");
            startActivityForResult(intent, REQUEST_GALLERY_CODE);
        
        else 
            Toast.makeText(getActivity().getApplicationContext(),"No Permissions",Toast.LENGTH_SHORT).show();
        
        return;
    
    super.onRequestPermissionsResult(requestCode,permissions,grantResults);

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
    if(requestCode == CAMERA_REQUEST)
        if(resultCode == Activity.RESULT_OK)
            Bitmap bmp = (Bitmap) data.getExtras().get("data");
            ByteArrayOutputStream stream = new ByteArrayOutputStream();

            bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
            byte[] byteArray = stream.toByteArray();

            Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray,0,byteArray.length);

            mImageView.setImageBitmap(bitmap);
        
    


private void initUI(View v) 

  [...] //initializes everything using findViewById()



DBListAdapter.class(我们的自定义适配器)

public class DBListAdapter extends BaseAdapter

private Context context;
private int layout;
private ArrayList<DBList> dblistsList;

public DBListAdapter(Context context, int layout, ArrayList<DBList> dblistsList) 
    this.context = context;
    this.layout = layout;
    this.dblistsList = dblistsList;


@Override
public int getCount() 
    return dblistsList.size();


@Override
public Object getItem(int position) 
    return dblistsList.get(position);


@Override
public long getItemId(int position) 
    return position;



private class ViewHolder
    ImageView imageView;
    TextView txtTitle, txtContent;



@Override
public View getView(int position, View view, ViewGroup viewGroup) 

    View row = view;
    ViewHolder holder = new ViewHolder();
    if(row==null)
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        row = inflater.inflate(layout, null);

        holder.txtTitle = row.findViewById(R.id.input_title);
        holder.txtContent = row.findViewById(R.id.input_content);
        holder.imageView = row.findViewById(R.id.fotoView);
        row.setTag(holder);
    
    else
        holder = (ViewHolder) row.getTag();

    

    DBList dbList = dblistsList.get(position);

    holder.txtTitle.setText(dbList.getTitle());
    holder.txtContent.setText(dbList.getContent());

    byte[] dblistImage = dbList.getImage();
    Bitmap bitmap = BitmapFactory.decodeByteArray(dblistImage, 0, dblistImage.length);

    holder.imageView.setImageBitmap(bitmap);
    return row;


问题出在这个适配器上。

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference at s***.d***.u***.th***ive.DBListAdapter.getView(DBListAdapter.java:78)

我们无法弄清楚如何将 Fragment_home.xml 中的 EditText 转换为 ViewHolder 所需的 TextView。

fragment_home.xml

[...]
<ImageView
    android:id="@+id/fotoView"
    android:layout_
    android:layout_
    android:layout_alignParentStart="true"
    android:layout_alignParentTop="true"
    android:background="@color/Gainsboro"
    app:srcCompat="@android:drawable/ic_menu_camera" />

<EditText
    android:id="@+id/input_title"
    android:layout_
    android:layout_
    android:hint="Title"
    android:inputType="text"
    android:maxLines="1"
    android:textAlignment="center"
    android:layout_above="@+id/input_content"
    android:layout_alignParentStart="true" />

<EditText
    android:id="@+id/input_content"
    android:layout_
    android:layout_
    android:hint="@string/hint_what"
    android:inputType="textMultiLine"
    android:textAlignment="center"
    android:layout_above="@+id/linearLayout"
    android:layout_alignParentStart="true"
    android:layout_marginBottom="33dp" /> [...]

任何帮助都将不胜感激,我现在​​正在燃烧,我当然不知道如何解决这个问题。如果你需要更多,就问我。现在有点累,所以可能会晚点重播。

【问题讨论】:

如果fragment_home.xml 是您的Fragment 的布局,那么ImageView 和那些TextViews 应该在列表项的单独布局中,R.id将作为 DBListAdapter 构造函数调用中的第二个参数传递。 将 ViewHolder 的类型从 TextView 更改为 EditText @MikeM。我使用了 的解决方案,现在它显示在我的网格中,但不是作为 TextView。我仍然可以“编辑”网格内的内容。 如果您不希望它们可编辑,请将&lt;EditText&gt;s 更改为&lt;TextView&gt;s。您在布局中指定的类型决定了 View 实际上是什么。将EditText 实例转换为TextView 不会“将其转换为”TextView。它只是告诉编译器你想如何处理这个对象。 @MikeM。明白了,谢谢 【参考方案1】:

okey .. 首先您需要创建新的 xml 文件并根据需要命名...假设它的名称是 list_reycle_view 然后将这些视图传递给它

<ImageView
    android:id="@+id/fotoView"
    android:layout_
    android:layout_
    android:layout_alignParentStart="true"
    android:layout_alignParentTop="true"
    android:background="@color/Gainsboro"
    app:srcCompat="@android:drawable/ic_menu_camera" />

<EditText
    android:id="@+id/input_title"
    android:layout_
    android:layout_
    android:hint="Title"
    android:inputType="text"
    android:maxLines="1"
    android:textAlignment="center"
    android:layout_above="@+id/input_content"
    android:layout_alignParentStart="true" />

<EditText
    android:id="@+id/input_content"
    android:layout_
    android:layout_
    android:hint="@string/hint_what"
    android:inputType="textMultiLine"
    android:textAlignment="center"
    android:layout_above="@+id/linearLayout"
    android:layout_alignParentStart="true"
    android:layout_marginBottom="33dp" />

然后 .. 替换这些行

LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    row = inflater.inflate(layout, null);

这一行

row= LayoutInflater.from(context).inflate(R.layout.list_recycle_view,viewGroup,false);

然后运行你的程序

【讨论】:

这就是解决方案,谢谢!现在我只需要重新设计我的gridview,它应该很好去! +1 我可能会在结果中添加它,它现在在我的列表中显示为 EditText 而不是 TextView。还有什么办法可以投吗? 您可以更新您的问题并解释您要投射的编辑文本..以及哪个文本视图【参考方案2】:
ViewHolder holder = null;
if (row == null) 
    LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    row = inflater.inflate(layout, null);
    holder = new ViewHolder();
    holder.txtTitle = row.findViewById(R.id.input_title);
    holder.txtContent = row.findViewById(R.id.input_content);
    holder.imageView = row.findViewById(R.id.fotoView);
    row.setTag(holder);

【讨论】:

?这只会改变 Object 的创建,而不是在 if 子句之外。仍然得到 NullPo 错误。

以上是关于无法在自定义适配器中将 EditText 转换为 TextView的主要内容,如果未能解决你的问题,请参考以下文章

EditText.SetText() 在自定义适配器中更改我的软键盘输入类型

在自定义适配器中隐藏软键盘

如何在自定义适配器中搜索?

如何在 customlistview 中维护每个 EditText 的值

Android - 通过 getView 函数在自定义 listView 适配器内设置 ImageView 的源无法正常工作

无法在内部类线程中将文本设置为 EditText 或 TextView [重复]