自定义视图中的Android findViewById()

18
我已经编写了自定义的视图,并在与其交互后想要更新其他一些视图。 主布局:
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/display_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="text"
        android:layout_centerHorizontal="true"
        android:tag="name"
        android:ems="10" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="number"
        android:ems="10"
        android:id="@+id/id_number"
        android:layout_centerHorizontal="true"
        android:layout_below="@id/display_name"/>

    <ge.altasoft.custom_views.IdNumber
        android:id="@+id/custom_id_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_below="@id/id_number"
        android:paddingLeft="35dip"
        custom:firstName="@id/display_name"/>
</RelativeLayout>

自定义视图布局:

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

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <EditText
        android:id="@+id/id_number_custom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="number"
        android:ems="10"
        android:paddingRight="35dip" />

    <ImageButton
        android:id="@+id/load_data_button"
        android:layout_width="30dip"
        android:layout_height="30dip"
        android:layout_centerVertical="true"
        android:src="@drawable/load_data"
        android:layout_toRightOf="@id/id_number_custom" />

</RelativeLayout>

自定义视图类、构造函数和监听器:

 private int firstNameViewID;

public IdNumber (Context context, AttributeSet attrs) {
        super(context, attrs);
        initViews();

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IdNumber);
        final int N = a.getIndexCount();
        for(int i = 0; i < N; i++){
            int attr = a.getIndex(i);
            switch(attr){
                case R.styleable.IdNumber_firstName:
                    firstNameViewID = a.getResourceId(attr, -1);
                    break;
            }
        }
        a.recycle();
    }



 private void initViews() {
        inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.id_number_edit_text_custom, this, true);
        editText = (EditText) findViewById(R.id.id_number_custom);
        loadButton = (ImageButton) findViewById(R.id.load_data_button);
        loadButton.setVisibility(RelativeLayout.INVISIBLE);
        loadData();
    }

private void loadData(){
        loadButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                EditText firstName = (EditText) findViewById(R.id.display_name);
                firstName.setText("Some Text");
            }
        });
    }
问题在于 EditText firstName = (EditText) findViewById(R.id.display_name); 返回了null。 我知道只是调用 findViewById() 会在我填充的布局中查找视图。
如果可能的话,如何从主布局获取id为 display_name 的EditText视图?
提前感谢。

不,我不想获取我的自定义视图,我想从主布局中获取其他视图,其ID为diplay_name。 - Jilberta
你正在解析XML文件,但没有存储返回的视图。你可以在该视图上使用findViewById方法。 - Siddhesh
7个回答

15
View Custmv;

 private void initViews() {
        inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        Custmv = inflater.inflate(R.layout.id_number_edit_text_custom, this, true);
        editText = (EditText) findViewById(R.id.id_number_custom);
        loadButton = (ImageButton) findViewById(R.id.load_data_button);
        loadButton.setVisibility(RelativeLayout.INVISIBLE);
        loadData();
    }

private void loadData(){
        loadButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                EditText firstName = (EditText) Custmv.getParent().findViewById(R.id.display_name);
                firstName.setText("Some Text");
            }
        });
    }

试试这样做。


你没明白 @Siddesh, editText = (EditText) findViewById(R.id.id_number_custom); loadButton = (ImageButton) findViewById(R.id.load_data_button); 这个是可以正常工作的,我可以从CustomView布局中获取视图,但我想从MainLayout中获取视图。 - Jilberta
好的,但是为什么你想从自定义视图类处理主布局? - Siddhesh
因为我想在与我的自定义视图交互后更新这些视图。 - Jilberta
我不确定,但可以尝试在OnClick监听器中使用类似于customview.this.getParent().findViewByID()的代码。 - Siddhesh
无法正常工作,因为我的自定义视图的父级将为空,只要我仅填充自定义视图所代表的布局。 - Jilberta

3

按照以下方式更改您的方法并检查它是否有效

private void initViews() {
    inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.id_number_edit_text_custom, this, true);
    View view = (View) inflater.inflate(R.layout.main, null);
    editText = (EditText) view.findViewById(R.id.id_number_custom);
    loadButton = (ImageButton) view.findViewById(R.id.load_data_button);
    loadButton.setVisibility(RelativeLayout.INVISIBLE);
    loadData();
} 

我尝试了这个Usman,但它不起作用,视图返回null。 - Jilberta
当LayoutInflater.inflate返回View时,无需将其强制转换为View。 - vilpe89

1
您可以尝试类似以下的内容:
在自定义视图构造函数中:
mContext = context;

下一步,在自定义视图中,您可以调用以下代码:

((MainActivity) mContext).updateText( text );

MainActivity 内定义:
public void updateText(final String text) {

     TextView txtView = (TextView) findViewById(R.id.text);
     txtView.setText(text);
}

它对我有效。


多次调用 findViewById() 是不好的,也不高效。如果您要重复使用它,请将其存储在一个 final 字段中以供引用。 - Moses Aprico

0
如果是固定布局,你可以这样做:
public void onClick(View v) {
   ViewGroup parent = (ViewGroup) IdNumber.this.getParent();
   EditText firstName = (EditText) parent.findViewById(R.id.display_name);
   firstName.setText("Some Text");
}

如果你想在灵活的布局中查找EditText,我稍后会帮助你。希望这可以帮到你。

只要我填充自定义视图所代表的布局,父级就为空。 - Jilberta

0
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;
    ImageHolder holder = null;
    if (row == null) {
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        row = inflater.inflate(layoutResourceId, parent, false);
        holder = new ImageHolder();
        editText = (EditText) row.findViewById(R.id.id_number_custom);
        loadButton = (ImageButton) row.findViewById(R.id.load_data_button);
        row.setTag(holder);
    } else {
        holder = (ImageHolder) row.getTag();
    }


    holder.editText.setText("Your Value");
    holder.loadButton.setImageBitmap("Your Bitmap Value");
    return row;
}

1
我认为你在回答其他问题。. . . - Jilberta
如果你遇到了像空指针这样的错误,那么你在初始化EditText和ImageButton时可能根据你的代码犯了错误... - Dhaval Patel

0

更新View(context) -> View(context, attrs, defStyleAttr)


1
欢迎来到Stack Overflow!虽然这段代码可能解决了问题,但是包括解释它如何以及为什么解决了问题将有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释并指出适用的限制和假设。 - Yunnosch

0
在你的构造函数中尝试这个。
MainActivity maniActivity = (MainActivity)context;
EditText firstName = (EditText) maniActivity.findViewById(R.id.display_name);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接