まず第一に、はい、このトピックに関する他のすべてのスレッドを読みました。そして、このサイトからのものだけでなく...(ほら、私は少しイライラしています)
それらのほとんどは、XMLファイルでid
の代わりにAndroid:id
を使用するようにアドバイスされています。やった。
他の人から、View.findViewById
はActivity.findViewById
とは異なる動作をすることを学びました。私もそれを処理しました。
location_layout.xml
では、次を使用します。
<FrameLayout .... >
<some.package.MyCustomView ... />
<LinearLayout ... >
<TextView ...
Android:id="@+id/txtLat" />
...
</LinearLayout>
</FrameLayout>
私の活動では:
...
setContentView( R.layout.location_layout );
そして私のカスタムビュークラスで:
...
TextView tv = (TextView) findViewById( R.id.txtLat );
null
を返します。 これを行うと、私のアクティビティは正常に動作します。おそらくActivity.findViewById
とView.findViewById
の違いが原因です。そこで、カスタムビューコンストラクターに渡されたコンテキストをローカルに保存して、次のことを試しました。
...
TextView tv = (TextView) ((Activity) context).findViewById( R.id.txtLat );
null
も返しました。
次に、カスタムビューを変更してViewGroup
をView
の代わりに拡張し、location_layout.xml
を変更してTextView
をカスタムビューの直接の子にし、View.findViewById
が想定どおりに動作するようにしました。驚き:それは何も解決しませんでした。
それで、私は一体何を間違っているのでしょうか?
コメントをお願いします。
nullを返します
おそらく早すぎて呼び出しているからでしょう。 onFinishInflate()
になるまで待ちます。 これはサンプルプロジェクトです カスタムView
がそのコンテンツにアクセスすることを示しています。
おそらく、findViewById
を呼び出す前にsetContentView
を呼び出していますか?その場合は、findViewById
を呼び出してみてくださいの後のsetContentView
を呼び出します
異なる画面密度に対応したレイアウトの複数のバージョンがないことを確認してください。既存のレイアウトに新しいIDを追加するときに一度この問題に遭遇しましたが、hdpiバージョンを更新するのを忘れていました。レイアウトファイルのすべてのバージョンを更新するのを忘れると、一部の画面密度では機能しますが、他の画面密度では機能しません。
私の場合、プロジェクトにはmain.xml
とmain2.xml
の2つのアクティビティがありました。最初から、main2
はmain
のコピーであり、main2
に新しいTextView
を追加するまではすべて正常に機能したため、R.id.textview1
はアプリの残りの部分で使用可能になりました。次に、標準の呼び出しで取得しようとしました:
TextView tv = (TextView) findViewById( R.id.textview1 );
そして、それは常にヌルでした。 onCreate
コンストラクターでmain2
ではなく、他のインスタンス化を行っていたことが判明しました。私が持っていた:
setContentView(R.layout.main);
の代わりに
setContentView(R.layout.main2);
この場所に到着した後、私はこれに気づきました。
他の場所で言及されている古典的な原因と一緒に:
setContentView()
の前にfindViewById()
を呼び出していることを確認してくださいid
がsetContentView()
に指定したビューまたはレイアウトにあることを確認してくださいid
が誤って異なるレイアウトで複製されないようにしてください標準レイアウトのカスタムビューで見つけたものがありますが、これはドキュメントに反します。
理論的には、カスタムビューを作成してレイアウトに追加できます( こちらを参照 )。ただし、そのような状況では、カスタム変数以外のレイアウト内のすべてのビューでid
属性が機能する場合があることがわかりました。私が使用するソリューションは次のとおりです。
FrameLayout
で、カスタムビューに必要なレイアウトプロパティと同じものに置き換えます。適切なid
、たとえばframe_for_custom_view
を指定します。onCreate
で:
setContentView(R.layout.my_layout);
FrameView fv = findViewById(R.id.frame_for_custom_layout);
MyCustomView cv = new MyCustomView(context);
fv.addView(cv);
カスタムビューをフレームに配置します。
カスタムビューで間違ったスーパーコンストラクターを呼び出すと、FindViewByIdがnullになる可能性があります。 IDタグはattrsの一部であるため、attrsを無視すると、IDが削除されます。
これは間違っているだろう
public CameraSurfaceView(Context context, AttributeSet attrs) {
super(context);
}
これは正しいです
public CameraSurfaceView(Context context, AttributeSet attrs) {
super(context,attrs);
}
@Override
protected void onStart() {
// use findViewById() here instead of in onCreate()
}
ExpandableListViewを使用し、タイトルに基づいてこの質問にぶつかった場合の回答
ExpandableListView実装の一部として、子ビューおよびグループビューでTextViewを操作しようとすると、このエラーが発生しました。
GetChildView()およびgetGroupView()メソッドの実装では、次のようなものを使用できます。
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.child_layout, null);
}
私はこれを見つけました ここ 。
私はAndroid/Eclipseにかなり慣れていないので、誤ってactivity_main.xml
ではなくfragment_main.xml
にUIを追加しました。それを理解するのに数時間かかった...
FWIW、私が必要とするのとまったく同じ方法でこれを解決した人は誰もいません。コンパイル時に不満はありませんが、実行時にnullビューを取得し、適切な順序で呼び出します。つまり、findViewById()after setContentView()です。問題は、私のビューがcontent_main.xmlで定義されていることでしたが、私のactivity_main.xmlでは、この1つのステートメントが欠けていました。
<include layout="@layout/content_main" />
それをactivity_main.xmlに追加すると、NullPointerはなくなりました。
私の特定のケースでは、リストビューにフッターを追加しようとしました。 onCreate()の次の呼び出しはnullを返していました。
TextView footerView = (TextView) placesListView.findViewById(R.id.footer);
IDで検索する代わりにフッタービューを拡大するようにこれを変更すると、この問題は解決しました。
View footerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_view, null, false);
私の場合は上記のようなものではなく、解決策はありませんでした。私の見解はレイアウト階層の奥深くにあると思います。私はそれを1レベル上に移動しましたが、もうヌルではありませんでした。
ここに私の特定のケースを投げたかっただけです。誰かが助けになるかもしれません。
次のようにAndroid UI XMLでディレクティブを使用していました。
親ビュー:
<FrameLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:tag="home_phone"
Android:background="@color/colorPrimary">
...
<include
layout="@layout/retry_button"
Android:visibility="gone" />
子ビュー(retry_button):
<com.foo.RetryButton
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/retry"
Android:layout_gravity="center"
Android:orientation="vertical"
Android:layout_width="100dp"
Android:layout_height="140dp">
.findViewById(R.id.retry)は常にnullを返します。しかし、IDを子ビューからincludeタグに移動すると、機能し始めました。
固定親:
<FrameLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:tag="home_phone"
Android:background="@color/colorPrimary">
...
<include
layout="@layout/retry_button"
Android:id="@+id/retry"
Android:visibility="gone" />
固定子:
<com.foo.RetryButton
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_gravity="center"
Android:orientation="vertical"
Android:layout_width="100dp"
Android:layout_height="140dp">
私の場合、ExpandableListViewを使用していて、Android:transcriptMode="normal"
を設定していました。これにより、展開可能なグループの子がほとんど表示されなくなり、リストをスクロールしたときにNULL例外が発生していました。
レイアウトリソースからアクティビティコンテンツを設定します。すなわち、setContentView(R.layout.basicXml)
;
私にとっては、同じアクティビティに対して2つのxmlレイアウトがありました。1つはポートレートモードで、もう1つは横長モードです。もちろん、landscape xmlのオブジェクトのidを変更しましたが、portraitバージョンで同じ変更を行うのを忘れていました。一方を変更した場合、もう一方のxmlに対しても同じことを行うか、実行またはデバッグして、変更していないIDが見つからない限り、エラーが発生しないことを確認してください。ああ、間抜けな間違い、なぜあなたは私をそう罰する必要がありますか?
私も同じ問題を抱えていますが、皆さんと共有する価値があると思います。カスタムレイアウトでfindViewByIdを検索する必要がある場合、たとえば:
public class MiniPlayerControllBar extends LinearLayout {
//code
}
コンストラクターでビューを取得することはできません。ビューが膨張した後、findViewByIdを呼び出す必要があります。それらはonFinishInflate
をオーバーライドできるメソッドです
同じ問題がありました。 GridViewのアダプターをオーバーライドし、各GridViewセルに独自のレイアウトを指定できるサードパーティライブラリを使用していました。
私は最終的に何が起こっているのかを理解しました。 Eclipseは、まだ示されていませんが、GridViewの各セルにライブラリのレイアウトxmlファイルを使用していました。私のカスタムアダプターでは、ランタイムではなくても、自分のプロジェクトのxmlリソースを使用していることが示されました。
したがって、私がしたことは、私のカスタムxmlレイアウトとIDがライブラリにまだ残っているものと異なることを確認し、プロジェクトをクリーンアップしてから、プロジェクトにあった正しいカスタムレイアウトの読み取りを開始することでした。
要するに、サードパーティのライブラリのアダプタをオーバーライドし、使用するアダプタの独自のレイアウトxmlを指定する場合は注意してください。プロジェクト内のレイアウトにライブラリ内のレイアウトと同じファイル名がある場合、本当に見つけにくいバグに遭遇する可能性があります!
上記のソリューションに加えて、tools:context=".TakeMultipleImages"
はmainfest.xmlファイルの同じ値です:Android:name=".TakeMultipleImages"
同じアクティビティ要素。コピーアンドペーストを使用して新しいアクティビティを作成するときに発生します
私の場合、レイアウトを拡大しましたが、子ビューはnullを返していました。もともと私はこれを持っていました:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false);
pbSpinner = (ProgressBar) findViewById(R.id.pbListviewFooter);
tvText = (TextView) findViewById(R.id.tvListviewFooter);
...
}
ただし、次のように変更すると機能しました:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false);
pbSpinner = (ProgressBar) footerView.findViewById(R.id.pbListviewFooter);
tvText = (TextView) footerView.findViewById(R.id.tvListviewFooter);
...
}
重要なのは、子ビューを取得するために、既に膨らんだレイアウトを具体的に参照することでした。つまり、footerView
を追加するには:
私の場合、親オブジェクトから親によってインスタンス化されたアダプターオブジェクトに呼び出しを移動すると、findViewByIdはnullを返しました。ここにリストされたトリックを成功せずに試行した後、findViewByIdを親オブジェクトに戻し、アダプターオブジェクトのインスタンス化中に結果をパラメーターとして渡しました。たとえば、親オブジェクトでこれを行いました:
Spinner hdSpinner = (Spinner)view.findViewById(R.id.accountsSpinner);
次に、アダプターオブジェクトの作成中にhdSpinnerをパラメーターとして渡しました。
mTransactionAdapter = new TransactionAdapter(getActivity(),
R.layout.transactions_list_item, null, from, to, 0, hdSpinner);
私の修正は、プロジェクトをきれいにすることでした。
上記のすべてを試してみましたが、何も機能しませんでした.. ImageView staticpublic static ImageView texture;
を作成し、その後texture = (ImageView) findViewById(R.id.texture_back);
を作成する必要がありましたが、これは良いアプローチではないと思いますが、これは本当に私の場合はうまくいきました:)
フラグメント内にいる場合、findViewByIdはnullを返すこともできます。ここで説明されているとおり: フラグメント内のfindViewById
GetView()を呼び出して、フラグメント内のトップレベルビューを返す必要があります。次に、レイアウト項目(ボタン、テキストビューなど)を見つけることができます
私の経験では、OnDestroyViewの後にコードが呼び出されたとき(フラグメントがバックスタックにあるとき)にもこれが発生する可能性があるようです。 。
レイアウトを膨らませる!! (IDを含む)
私の場合、要素が書き込まれたレイアウトが膨張していないため、findViewById()はnullを返しました...
例えば。 fragment_layout.xml
<ListView
Android:id="@+id/listview">
inflater.inflate(R.layout.fragment_layout、...、...);を実行していないため、findViewById(R.id.listview)はnullを返しました。その前に。
この答えがあなたの一部を助けることを願っています。
アクティビティIDのフィールドの1つが他のアクティビティのIDと一致していたため、クラッシュしました。一意のIDを指定して修正しました。
LoginActivity.xmlのパスワードフィールドidでは、「password」でした。私の登録アクティビティでは、id r_passwordを指定して修正しましたが、null以外のオブジェクトを返しました。
password = (EditText)findViewById(R.id.r_password);
ListView
のカスタムビューを作成しようとしたときに、同様の問題に直面していました。
私はこれを簡単に解決しました:
public View getView(int i, View view, ViewGroup viewGroup) {
// Gets the inflater
LayoutInflater inflater = LayoutInflater.from(this.contexto);
// Inflates the layout
ConstraintLayout cl2 = (ConstraintLayout)
inflater.inflate(R.layout.custom_list_view, viewGroup, false);
//Insted of calling just findViewById, I call de cl2.findViewById method. cl2 is the layout I have just inflated.
TextView tv1 = (TextView)cl2.findViewById(cl2);