这个问题难倒了我。

我需要从自定义布局类中调用一个活动方法。这样做的问题是,我不知道如何从布局内访问活动。

ProfileView

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();
    }
}

ProfileActivity

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与它一起传入。两个问题:

我是否将正确的上下文传递到Profileview? 我如何从上下文获得包含活动?


当前回答

在Kotlin中:

tailrec fun Context.activity(): Activity? = when {
  this is Activity -> this
  else -> (this as? ContextWrapper)?.baseContext?.activity()
}

其他回答

Kotlin机器人速记扩展版本的西奥的解决方案

private fun Context?.getParentActivity() : AppCompatActivity? = when {
    this is ContextWrapper -> if (this is AppCompatActivity) this else this.baseContext.getParentActivity()
    else -> null
}

以上用法在此解释

上下文可以是应用程序、服务、活动等等。

通常情况下,Activity中视图的上下文是Activity本身,所以你可能认为你可以将这个context强制转换为Activity,但实际上你不能总是这样做,因为context在这里也可以是ContextThemeWrapper。

ContextThemeWrapper在AppCompat和Android的最新版本中被大量使用(感谢布局中的Android:theme属性),所以我个人永远不会执行这种强制转换。

所以简单的回答是:你不能可靠地从视图中的上下文中检索一个活动。通过调用以Activity为参数的方法将Activity传递给视图。

在Kotlin中:

tailrec fun Context.activity(): Activity? = when {
  this is Activity -> this
  else -> (this as? ContextWrapper)?.baseContext?.activity()
}

Activity是Context的专门化,所以,如果你有一个Context,你已经知道你打算使用哪个Activity,并且可以简单地将a转换为c;其中a是活动,c是上下文。

Activity a = (Activity) c;

这个方法应该是有用的..!

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;

    }

我希望这能有所帮助。编码快乐!