从 Activity C# 之外的 OnClick 事件启动 Activity

Posted

技术标签:

【中文标题】从 Activity C# 之外的 OnClick 事件启动 Activity【英文标题】:Start Activity from an OnClick event outside an Activity C# 【发布时间】:2021-02-05 16:27:27 【问题描述】:

我会尽我所能解释自己。 (Xamarin.android C#)

我有一个名为 PhotoAlbumAdapter: RecyclerView.Adapter 的类,其中创建、分配和配置包含客户端图像的 RecyclerView 的资源,但该类在 MainActivity: Activity 公共类之外。

这里我有OnClick 方法,当单击 RecyclerView 中的一个图像时显然会触发该方法,我使用该方法保存在某些公共/全局变量中选择的图像的 ID。我的问题是我不知道如何使用从OnClick 获得的结果来启动另一个类:Activity,它会在其中加载我点击的那个客户端的详细信息

尝试:

         var Intent = new Android.Content.Intent (this, typeof (Details));
         StartActivity(Intent);

但除非它在MainActivity: Activity 或其他活动中,否则它不起作用。错误告诉我“StartActivity”它在当前上下文中不存在。

除了这个之外,还有什么想法可以触发我的活动Details.cs

我附上代码。

    public class PhotoViewHolder : RecyclerView.ViewHolder
        
            public ImageView Image  get; private set; 
            public TextView Caption  get; private set; 
            public PhotoViewHolder(View itemView, Action<int> listener)
                : base(itemView)
            
                Image = itemView.FindViewById<ImageView>(Resource.Id.imageView);
                Caption = itemView.FindViewById<TextView>(Resource.Id.textView);
    
                itemView.Click += (sender, e) => listener(base.LayoutPosition);
            
        
    
        public class PhotoAlbumAdapter : RecyclerView.Adapter
        
            public event EventHandler<int> ItemClick;
    
            PhotoAlbum mPhotoAlbum;
    
            public PhotoAlbumAdapter(PhotoAlbum photoAlbum)
            
                mPhotoAlbum = photoAlbum;
            
    
            public override RecyclerView.ViewHolder
                OnCreateViewHolder(ViewGroup parent, int viewType)
            
                View itemView = LayoutInflater.From(parent.Context).
                Inflate(Resource.Layout.LCardView, parent, false);
    
                PhotoViewHolder vh = new PhotoViewHolder(itemView, OnClick);
                return vh;
            
    
            public override void
                OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
            
                try
                
                    PhotoViewHolder vh = holder as PhotoViewHolder;
    
                    vh.Image.SetImageBitmap(GetImageBitmapFromUrl(mPhotoAlbum[position].PhotoID));
                    vh.Caption.Text = mPhotoAlbum[position].Caption;
                
                catch (Exception Ex)
                
                string LineErrorNumber = Ex.StackTrace.Substring(Ex.StackTrace.Length - 7, 7);
            
    
        

        public override int ItemCount
        
            get  return mPhotoAlbum.NumPhotos; 
        


void OnClick(int position)
            
                try
                 
                    VarGlobal.gIdRecyclerMaterial=(position); 
                    Busqueda.Globales.IdSeleccionado = Convert.ToInt32(mPhotoAlbum[position].TipoMaterial.Substring(2)); 


                       char c = mPhotoAlbum[position].TipoMaterial[0]; 
                        VarGlobal.gNombreMaterialR = Convert.ToString(c);
        
                        //Trigger detalles... 
//Need it here ... ********************************************************************************
                       
                        //var Intent = new Android.Content.Intent(this, typeof(Details));
                        //StartActivity(Intent);
    
                    
                
                catch (Exception Ex)
                
                    string LineErrorNumber = Ex.StackTrace.Substring(Ex.StackTrace.Length - 7, 7);
                
                    
    
            private Bitmap GetImageBitmapFromUrl(string url)
            
                Bitmap imageBitmap = null;
    
                using (var webClient = new WebClient())
                
                    var imageBytes = webClient.DownloadData(url);
                    if (imageBytes != null && imageBytes.Length > 0)
                    
                        imageBitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
                    
                
    
                return imageBitmap;
            
    
        
    

【问题讨论】:

你没有任何名为Details的类。 您的ViewHolder 子类在OnCreateViewHolder 中通过View,并且所有Android 视图都包含您可以使用的上下文(即yourViewHolderContext.StartActivity...):docs.microsoft.com/en-us/dotnet/api/…跨度> 是的,我愿意@Jason 不在您发布的代码中。该文件可能被命名为Details.cs,但这并不意味着该类被命名为Details。你可以为文件命名任何你想要的名字,这与里面的类的名字无关。 【参考方案1】:

适配器不应该对活动或上下文有任何了解。一般来说,我会使用一个接口来处理适配器行上的点击事件之间的回调并执行我想要的一些操作..

创建一个接口来处理Adapter和Activity之间的点击事件。

interface OnItemClickListener 

  void onItemClick(int position);

将其作为参数添加到您的 Adapters 构造函数并将回调转发到您的 ViewHolder

public PhotoAlbumAdapter(PhotoAlbum photoAlbum, OnItemClickListener clickListener)

     mPhotoAlbum = photoAlbum;
     mClickListener = clickListener;


public PhotoViewHolder(View itemView, OnItemClickListener listener): base(itemView)

     itemView.Click += (sender, e) => listener(base.LayoutPosition);

Activity扩展接口,在初始化时将clickListener传递给适配器并处理回调

public class MainActivity : OnItemClickListener

    protected override void OnCreate(Bundle bundle)
    
        base.OnCreate(bundle);
        adapter = PhotoAlbumAdapter(photoAlbum, this)
    

    ....

    protected override void onItemClick(int position)
    
         // use item position to get some data to add to the Intent
         var Intent = new Android.Content.Intent (this, typeof (Details));
         StartActivity(Intent);
    

【讨论】:

抱歉,我无法复制您的答案。可能是做错了什么。在“公共类 PhotoAlbumAdapter:RecyclerView.Adapter”中创建接口后,我收到错误:“可访问性不一致......”。由于我使用的是 Xamarin.Android,是否应该有所改变? 抱歉,我尝试用 c# 编写此代码,但实际上我在日常工作中使用 Java 和 Kotlin,因此语法可能有误!而不是复制和粘贴,您应该能够在这里使用界面重新创建架构? 我明白了。无论如何都非常感谢。我会继续努力的。 是的,我终于成功了。我所做的是创建 OnClick 方法,但这次是在公共类 MainActivity : Activity 上而不是在外部,然后进行引用,得到如下内容:View itemView = LayoutInflater.From(parent.Context)。 Inflate(Resource.Layout.LCardView, parent, false); MainActivity MyClass = new MainActivity(); PhotoViewHolder vh = new PhotoViewHolder(itemView, MyClass.OnClick);返回 vh; 看来@KennyAli 评论打破了一些核心编码原则,适配器不应该对 MainActivity 有任何了解,更不用说构造一个。正确的方法是使用一个接口作为活动和适配器之间的回调。

以上是关于从 Activity C# 之外的 OnClick 事件启动 Activity的主要内容,如果未能解决你的问题,请参考以下文章

从 Activity 到特定选项卡/片段的按钮 OnClick

从 Activity 上下文之外调用 startActivity()

如何在 DialogInterface.OnClickListener.onClick() 中获取 Activity 上下文?

将应用小部件放置在 Activity 之外的主屏幕上

在Activity中同时重写onTouchEvent()和onClick()方法,该怎样获得被点击的

Onclick 在 div 之外隐藏 div [重复]