これは私が困惑しています。
カスタムレイアウトクラス内からアクティビティメソッドを呼び出す必要があります。これの問題点は、レイアウト内からアクティビティにアクセスする方法がわからないことです。
public class ProfileView extends LinearLayout
{
TextView profileTitleTextView;
ImageView profileScreenImageButton;
boolean isEmpty;
ProfileData data;
String name;
public ProfileView(Context context, AttributeSet attrs, String name, final ProfileData profileData)
{
super(context, attrs);
......
......
}
//Heres where things get complicated
public void onClick(View v)
{
//Need to get the parent activity and call its method.
ProfileActivity x = (ProfileActivity) context;
x.activityMethod();
}
}
public class ProfileActivityActivity extends Activity
{
//In here I am creating multiple ProfileViews and adding them to the activity dynamically.
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.profile_activity_main);
}
public void addProfilesToThisView()
{
ProfileData tempPd = new tempPd(.....)
Context actvitiyContext = this.getApplicationContext();
//Profile view needs context, null, name and a profileData
ProfileView pv = new ProfileView(actvitiyContext, null, temp, tempPd);
profileLayout.addView(pv);
}
}
上記のとおり、profileViewをプログラム的にインスタンス化し、それをactivityContextに渡しています。 2つの質問
あなたのActivity
から、あなたのレイアウトのthis
としてContext
を渡すだけです:
ProfileView pv = new ProfileView(this, null, temp, tempPd);
その後、レイアウトにContext
が入りますが、それが実際にあなたのActivity
であることがわかり、必要なものが揃うようにキャストすることができます。
Activity activity = (Activity) context;
Androidには2つの異なるコンテキストがあります。 1つはあなたのアプリケーション用(それをBIG用と呼びましょう)そしてもう1つは各ビュー(それをアクティビティコンテキストと呼びましょう)用です。
LinearLayoutはビューなので、アクティビティコンテキストを呼び出す必要があります。アクティビティから呼び出すには、単に "this"を呼び出します。とても簡単ですね。
使うとき
this.getApplicationContext();
あなたはBIGコンテキストを呼び出します。これはあなたのアプリケーションを説明するものでビューを管理することはできません。
Androidの大きな問題は、コンテキストがあなたの活動を呼び出せないことです。誰かがAndroidの開発を始めるときにこれを避けるのは大したことです。クラスをコーディングするためのより良い方法を見つける必要があります(または、「コンテキストコンテキスト」を「アクティビティアクティビティ」に置き換えて、必要に応じて「コンテキスト」にキャストする必要があります)。
よろしく。
私の答えを更新するためだけに。あなたのActivity context
を取得する最も簡単な方法はあなたのstatic
にActivity
インスタンスを定義することです。例えば
public class DummyActivity extends Activity
{
public static DummyActivity instance = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Do some operations here
}
@Override
public void onResume()
{
super.onResume();
instance = this;
}
@Override
public void onPause()
{
super.onPause();
instance = null;
}
}
そして、あなたのTask
、Dialog
、View
で、あなたはあなたのActivity context
を得るためにそのような種類のコードを使うことができます:
if (DummyActivity.instance != null)
{
// Do your operations with DummyActivity.instance
}
これは、フラグメントまたはカスタムビューのUI内で操作するときにContext
をActivity
に変換するのに成功したものです。 ContextWrapperを再帰的に解凍するか、失敗した場合はnullを返します。
public Activity getActivity(Context context)
{
if (context == null)
{
return null;
}
else if (context instanceof ContextWrapper)
{
if (context instanceof Activity)
{
return (Activity) context;
}
else
{
return getActivity(((ContextWrapper) context).getBaseContext());
}
}
return null;
}
カスタムレイアウトクラス(Activityクラス以外)からアクティビティメソッドを呼び出す場合は、インターフェイスを使用してデリゲートを作成する必要があります。
それはテストされておらず、私はそれを正しくコーディングしました。しかし、私はあなたが望むものを達成する方法を伝えています。
まず最初にcreateとInterface
interface TaskCompleteListener<T> {
public void onProfileClicked(T result);
}
public class ProfileView extends LinearLayout
{
private TaskCompleteListener<String> callback;
TextView profileTitleTextView;
ImageView profileScreenImageButton;
boolean isEmpty;
ProfileData data;
String name;
public ProfileView(Context context, AttributeSet attrs, String name, final ProfileData profileData)
{
super(context, attrs);
......
......
}
public setCallBack( TaskCompleteListener<String> cb)
{
this.callback = cb;
}
//Heres where things get complicated
public void onClick(View v)
{
callback.onProfileClicked("Pass your result or any type");
}
}
そしてこれを任意のアクティビティに実装します。
そしてそれを好きに呼ぶ
ProfileView pv = new ProfileView(actvitiyContext, null, temp, tempPd);
pv.setCallBack(new TaskCompleteListener
{
public void onProfileClicked(String resultStringFromProfileView){}
});
コンテキストは、アプリケーション、サービス、アクティビティなどです。
通常、アクティビティ内のビューのコンテキストはアクティビティ自体なので、このコンテキストをアクティビティにキャストすることはできますが、実際には常に行うことはできません。この場合、コンテキストはContextThemeWrapperになることもあります。
ContextThemeWrapperは最近のバージョンのAppCompatとAndroid(レイアウトのAndroid:theme属性のおかげで)で多用されているので、私は個人的にこのキャストを実行することは決してないでしょう。
簡単に言うと、ビュー内のコンテキストから確実にアクティビティを取得することはできません。パラメータとしてActivityを受け取るメソッドを呼び出すことによって、Activityをビューに渡します。
ビューにgetApplicationContext()を使用することはありません。
ビューはアクティビティに関連付けられているため、常にアクティビティのコンテキストにする必要があります。また、あなたはカスタムテーマセットを持っているかもしれず、そしてアプリケーションのコンテキストを使用するとき、すべてのテーマは失われるでしょう。さまざまなバージョンのコンテキスト については、こちら を参照してください。
そして、コトリンでは:
tailrec fun Context.activity(): Activity? = when {
this is Activity -> this
else -> (this as? ContextWrapper)?.baseContext?.activity()
}
Convertアクティビティを使用しました
Activity activity = (Activity) context;
この方法は役に立ちます。
public Activity getActivityByContext(Context context){
if(context == null){
return null;
}
else if((context instanceof ContextWrapper) && (context instanceof Activity)){
return (Activity) context;
}
else if(context instanceof ContextWrapper){
return getActivity(((ContextWrapper) context).getBaseContext());
}
return null;
}
これが役に立つことを願っています..メリーコーディング!
アクティビティはコンテキストを特殊化したものです。したがって、コンテキストがある場合は、どのアクティビティを使用するつもりか知っていて、単純にaからc;ここで、aはアクティビティで、cはコンテキストです。
Activity a = (Activity) c;