片段中的findViewById


1035

我试图在一个Fragment中创建一个ImageView,该ImageView引用我在Fragment的XML中创建的ImageView元素。但是,该findViewById方法仅在我扩展Activity类时才有效。无论如何,我也可以在Fragment中使用它吗?

public class TestClass extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        ImageView imageView = (ImageView)findViewById(R.id.my_image);
        return inflater.inflate(R.layout.testclassfragment, container, false);
    }
}

findViewById方法上有一个错误,指出该方法未定义。


使用适用于Android的ButterKnife viewbinding库。还要演示它是如何工作的,如何在您的android应用程序开发中进行集成和使用,以使您的开发更快。
Shomu,

“一些”时间已经过去,但您仍未接受答案。您能否选择最有帮助的答案,以便将其标记为已回答?
David3103 '19

鼓励使用数据绑定orang视图绑定代替手动findViewById
mochadwi

Answers:


1433

使用getView()或实现该onViewCreated方法的View参数 。它返回片段的根视图onCreateView()方法返回的视图。有了这个你可以打电话findViewById()

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    ImageView imageView = (ImageView) getView().findViewById(R.id.foo);
    // or  (ImageView) view.findViewById(R.id.foo); 

正如getView()只有在之后才能使用的那样onCreateView(),您不能onCreate()onCreateView()在片段的内部方法使用它


323
注意:它仅在onCreateView()之后起作用。因此,您不能在onCreate()中使用它
Dmitry Zaytsev 2012年

7
那么,如果onCreate不合适,我可以重写以实现此功能的函数是什么?
Nico AD

16
如果ImageView是来自夸大的布局,这无济于事-有关详细信息,请参见我的答案。否则,onCreateView是执行此操作的正确位置@ N-AccessDev
MattJenko 2013年

25
最佳方法是onViewCreated方法
advantej 2013年

37
文档指出,这onActivityCreated()是查找和存储对视图的引用的推荐位置。您必须通过将它们重新设置为nullin 清理这些存储的引用,onDestroyView()否则将泄漏Activity
Monstieur 2014年

618

您需要膨胀片段的观点,并呼吁findViewById()View它的回报。

public View onCreateView(LayoutInflater inflater, 
                         ViewGroup container, 
                         Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.testclassfragment, container, false);
     ImageView imageView = (ImageView) view.findViewById(R.id.my_image);
     return view;
}

4
当您执行V.findViewById(R.id.someid)时,请确保这仅适用于展开视图中的所有小部件。如果他要膨胀的imageView在膨胀视图之外怎么办?
拉纳克2011年

18
然后,“拥有”并膨胀了imageView的类需要提供对其的公共访问。不过,这是非常糟糕的做法。片段只能访问其布局中存在的UI元素。
LeffelMania

1
看起来您的代码有问题(从后台线程更新UI),而不是我的。
LeffelMania

1
谢谢,这很有用。作为不相关的注释:尝试在代码中坚持Java命名约定。“ V”在Java中看起来不像变量名。
altumano 2014年

3
这应该是正确的答案。被接受的人留下了你NullPointerException
马查多

132

Fragment类内部,您将获得onViewCreated()重写方法,在该方法中,您应始终初始化视图,因为在此方法中,您将获得视图对象,通过该对象您可以找到视图,例如:

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    view.findViewById(R.id.yourId).setOnClickListener(this);

    // or
    getActivity().findViewById(R.id.yourId).setOnClickListener(this);
}

切记,如果使用Fragment,onViewCreated()则返回null或super.onCreateView()onCreateView()方法返回时不会自动调用该方法。默认情况下将ListFragment作为默认ListFragment返回调用FrameLayout

注意:getView()一旦onCreateView()执行成功,就可以在类的任何位置获取片段视图。即

getView().findViewById("your view id");

4
令我惊讶的是,没有多少人支持此响应-这是在片段上设置侦听器的正确方法...也许这是API的一项新开发。
桑尼2014年

使用view传递到onViewCreated仍然会导致,NullPointerException但使用getActivity()可以。有什么想法吗?
dVaffection 2015年

@dVaffection可能是您没有在片段的onCreateView()生命周期方法中返回非null视图。现在,在使用getActivity的情况下,您是从活动中获取视图,而不是片段主视图,这取决于您传递的ID。请检查您是否从onCreateView返回非空视图?那让我知道
Ankur Chaudhary

@AnkurChaudhary我从onCreateView方法返回视图。我刚刚调试了一下,结果发现这里有一个布局(以我为例FrameLayout)。话虽这么说,当我试图找到一个元素返回null。为什么会这样呢?
dVaffection

@dVaffection您能否分享您的片段类和相应的布局。
Ankur Chaudhary

66

我意识到这是一个古老的问题,但是普遍的答案仍有待改进。

问题尚不清楚,需要什么imageView-是将其作为视图传递回去,还是仅保存引用以供以后使用?

无论哪种方式,如果ImageView都来自膨胀的布局,则执行此操作的正确方法是:

public class TestClass extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.testclassfragment, container, false);
        ImageView imageView = (ImageView)v.findViewById(R.id.my_image);
        return v;
    }
}

1
那如何从ListFragment更新imageView?这是否需要FragmentManager?换句话说,如何从单独类的onListItemClick的详细信息片段中更新imageView?
whyoz

1
您可以将对imageView的引用保存在方便的位置,或者在需要时保存fragment.getView()。findViewById(R.id.my_image)。在ListFragment中,假设图像位于列表项中,通常会在Adapter的getView方法中使用列表视图项的setTag / getTag方法创建一个引用持有人-有许多有关此方法的示例。
MattJenko

47

首先获取片段视图,然后从该视图获取ImageView。

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.testclassfragment, container, false);
    ImageView imageView = (ImageView) view.findViewById(R.id.my_image);
    return view;
}

那么,onCreate方法在Fragment中有用吗?
Tsunaze 2011年

onCreateView创建并返回与片段关联的视图层次结构.onCreate被调用以进行片段的初始创建。确实,这取决于您使用这些方法编写的内容。
xevincent 2011年

好的,但是如何在onCreate中声明变量?因为View在onCreateView方法内部。
Tsunaze 2011年

@Tsunaze您是否曾经从onCreate方法中找到如何执行此操作?
StuStirling,2012年

1
我同意。该答案应标记为解决方案。
鲍里斯·卡洛夫

25

您也可以在“ onActivityCreated方法”中执行此操作。

public void onActivityCreated(Bundle savedInstanceState) { 
      super.onActivityCreated(savedInstanceState);
}

就像他们在这里所做的一样:http : //developer.android.com/reference/android/app/Fragment.html (在API级别28中已弃用)

getView().findViewById(R.id.foo);

getActivity().findViewById(R.id.foo);

是可能的。



17

您可以重写onViewCreated(),在所有视图膨胀后立即调用。这是填写Fragment的成员View变量的正确位置。这是一个例子:

class GalleryFragment extends Fragment {
    private Gallery gallery;

    (...)

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        gallery = (Gallery) view.findViewById(R.id.gallery);
        gallery.setAdapter(adapter);
        super.onViewCreated(view, savedInstanceState);
    }
}

17

Fragment类内部,我们获得了onViewCreated()重写方法,该方法应该始终初始化视图,因为在此方法中,我们得到view对象。使用该对象,我们可以找到如下所示的视图:

class MyFragment extends Fragment {
    private ImageView imageView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.my_fragment_layout, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        //initialize your view here for use view.findViewById("your view id")
        imageView = (ImageView) view.findViewById(R.id.my_image);
    }
}

2
优秀的表现很好!非常感谢
Vivek

15

方法getView()不适用于OnCreate和类似方法之外的片段。

有两种方法,将视图传递给oncreate上的函数(这意味着只能在创建视图时运行函数)或将视图设置为变量:

private View rootView;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
    rootView = inflater.inflate(R.layout.fragment_contatos, container, false);
}

public void doSomething () {
    ImageView thumbnail = (ImageView) rootView.findViewById(R.id.someId);
}

11

1)首先膨胀Fragment的布局,然后可以使用findviewbyId。

View view = inflater.inflate(R.layout.testclassfragment, container, false);
             ImageView imageView = (ImageView) view.findViewById(R.id.my_image);
             return view;

10
EditText name = (EditText) getView().findViewById(R.id.editText1);
EditText add = (EditText) getView().findViewById(R.id.editText2);  


9

同意调用findViewById()View。

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View V = inflater.inflate(R.layout.testclassfragment, container, false);
    ImageView imageView = (ImageView) V.findViewById(R.id.my_image);

    return V;
}

9

注意 :

从API级别26开始,您还不需要专门转换findViewById的结果,因为它使用推断为其返回类型。

所以现在您可以简单地做

public View onCreateView(LayoutInflater inflater, 
                         ViewGroup container, 
                         Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.testclassfragment, container, false);
     ImageView imageView =  view.findViewById(R.id.my_image); //without casting the return type
     return view;
}

1
没有演员解释的东西帮助了我。
shaurya uppal

8

根据API级别11的文档

参考,在Back Stack中 http://developer.android.com/reference/android/app/Fragment.html

短代码

/**
 * The Fragment's UI is just a simple text view showing its
 * instance number.
 */
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.hello_world, container, false);
    View tv = v.findViewById(R.id.text);
    ((TextView)tv).setText("Fragment #" + mNum);
    tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb));
    return v;
}


7

试试这个对我有用

public class TestClass extends Fragment {
    private ImageView imageView;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.testclassfragment, container, false);
        findViews(view);
        return view;
    }

    private void findViews(View view) {
        imageView = (ImageView) view.findViewById(R.id.my_image);
    }
}

是的,这个代码在这里是好的。您对其他人的编辑不是。
OneCricketeer

@ cricket_007好的,您能看到我吗?
Bipin Bharti

对不起,我不太懂您的英语,但是现在一切都已解决。我什么也没给你看。
OneCricketeer

5

实现此目的的最佳方法如下:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

rootView = inflater.inflate(R.layout.testclassfragment, container, false);
        ImageView imageView = (ImageView) rootView.findViewById(R.id.my_image);
        return rootView
}

这样,rootView可以用于xml布局中定义的每个控件,并且这种方式的代码更加简洁。

希望这可以帮助 :)


我认为这可能是可行的,但是那没有用
Mike Brian Olivera

5

1)声明您的布局文件。

public View onCreateView(LayoutInflater inflater,ViewGroup container, 
                                 Bundle savedInstanceState) {
    return inflate(R.layout.myfragment, container, false);
}

2)然后,获取您的视图的ID

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    TextView nameView = (TextView) view.findViewById(R.id.textview1);
}

4

使用gradle 骨架插件,它将自动根据您的布局生成视图持有者类。

public class TestClass extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        MyLayout myLayout = new MyLayout(inflater, container, false);
        myLayout.myImage.setImageResource(R.drawable.myImage);
        return myLayout.view;
    }
}

现在假设您ImageViewmy_layout.xml文件中有一个声明,它将自动为您生成myLayout类。


4

尝试这个:

View v = inflater.inflate(R.layout.testclassfragment, container, false);
ImageView img = (ImageView) v.findViewById(R.id.my_image);

return v;

4

尝试

private View myFragmentView;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
{
myFragmentView = inflater.inflate(R.layout.myLayoutId, container, false);
myView = myFragmentView.findViewById(R.id.myIdTag)
return myFragmentView;
}

没有理由去这个领域。您可以随时拨打getView()
OneCricketeer

3

您可以在Fragment 的方法内部findViewById()使用Activity对象进行调用public void onAttach(Activity activity)

将活动保存到变量中,例如:

Fragment类中private Activity mainActivity;onAttach()方法中: this.mainActivity=activity;

最后,通过vairable执行每个findViewById: mainActivity.findViewById(R.id.TextView);


3

还有另一种方法称为onViewCreated。

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ImageView imageView = (ImageView) view.findViewById(R.id.imageview1);
}

2

里面的onCreateView方法

1)首先,您必须膨胀要添加的布局/视图,例如。线性布局

LinearLayout ll = inflater.inflate(R.layout.testclassfragment, container, false);

2)然后您可以从布局中找到您的imageView id

ImageView imageView = (ImageView)ll.findViewById(R.id.my_image);

3)返回膨胀的布局

return ll;

这与LeffelMania的答案相同。
Reti43

2

你必须给视图充气

public class TestClass extends Fragment {

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.testclassfragment, container, false);
    ImageView imageView = (ImageView)v.findViewById(R.id.my_image);
    return v
}}

2

在片段中,我们需要该窗口的视图,以便我们对该片段进行onCreateView。

然后获取视图并使用它来访问该视图元素的每个视图ID。

  class Demo extends Fragment
    {
        @Override
        public View onCreateView(final LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState)
        {
            View view =inflater.inflate(R.layout.demo_fragment, container,false);
            ImageView imageview=(ImageView)view.findViewById(R.id.imageview1);

            return view;
        }
    }

1)这对其他答案有什么帮助?2)您似乎回答了两次
OneCricketeer

2

布局充气机在这里出现。Layout Inflater是一个使我们能够在Java代码中使用XML视图的类。因此,您可以使用以下代码在变量v中扩展根xml视图。然后使用v,您可以找到根视图v的子视图。

public class TestClass extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.testclassfragment, container, false);
    ImageView imageView = (ImageView)v.findViewById(R.id.my_image);
    return v;
    }
}

1

使用此类操作最简单的方法是使用黄油刀。这样,您就可以通过@OnClick()如下所述添加尽可能多的Onclciklisteners:

public class TestClass extends Fragment {
    @BindView(R.id.my_image) ImageView imageView;
    @OnClick(R.id.my_image)
    public void my_image_click(){
        yourMethod();
    }
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view=inflater.inflate(R.layout.testclassfragment, container, false);
        ButterKnife.bind(getActivity,view);
        return view;
    }
}

为什么不赞成投票,如果您使用此选项,则可以在on语句中使用多个onclicks。
阿米特(Amit)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.