I'm trying to implement something similar to OnBackPressed() in a fragment in Xamarin, but the only solutions I found so far are for Java.
Here is one example in Java that does what I want:
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
#Override
public void handleOnBackPressed() {
Toast.makeText(mContext, "back pressed", Toast.LENGTH_SHORT).show();
// And when you want to go back based on your condition
if (yourCondition) {
this.setEnabled(false);
requireActivity().onBackPressed();
}
}
};
How could I go about converting that piece of code into C#?
UPDATE
Create an interface for handling your event:
public interface IOnBackPressedHandler
{
bool OnBackPressed();
}
In your activity(below is just an example) setup your interface callback as follows
public class FragActivity : AppCompatActivity
{
public override void OnBackPressed()
{
Fragment fragment = SupportFragmentManager.FindFragmentById(Resource.Id.yourFragmentId);
if (!(fragment is IOnBackPressedHandler) || !((IOnBackPressedHandler)fragment).OnBackPressed()) {
base.OnBackPressed();
}
}
}
Finally, your fragment would look something like that :
public class SomeFragment : Fragment, IOnBackPressedHandler
{
public bool OnBackPressed()
{
//Callbacks will be received here.
return true;
}
}
Hope this makes it easier to understand. You can also make this method a part of your base Fragment mark it as virtual and then have all classes inherit this to keep overriding it...
OG answer:
Well you cannot have anonymous classes in C#, So just create a Class that inherits this Abstract class and you're good:
public class HandleOnBackPressedCallback : OnBackPressedCallback
{
public HandleOnBackPressedCallback(bool enabled) : base(enabled)
{
}
public override void HandleOnBackPressed()
{
Toast.MakeText(context, "back pressed", ToastLength.Long).Show();
// And when you want to go back based on your condition
if (yourCondition)
{
this.setEnabled(false);
requireActivity().onBackPressed();
}
}
}
Good luck!!
Related
I have a pretty basic understanding of inheritance and so when using it there are a few moments like this where I find it difficult to understand what's fully happening and it probably doesn't help that I'm most likely not using it properly.
Anyways though I have these 3 classes
public abstract class EffectBase
{
public enum EffectType
{
harm,
help,
self
}
public EffectType type;
public float duration;
public void Activate()
{
Debug.Log("Activating effect");
ApplyEffect();
}
public abstract void ApplyEffect();
public abstract void End();
}
public class Player : MonoBehaviour
{
public List<EffectBase> effects = new List<EffectBase>();
void Update()
{
if (Input.GetKeyDown("q"))
{
Debug.Log("Q pressed");
AddEffect(new SpeedEffect());
}
}
public void AddEffect(EffectBase effect)
{
Debug.Log("Adding effect");
effects.Add(effect);
effect.Activate();
}
}
public class SpeedEffect : EffectBase
{
public override void ApplyEffect()
{
Debug.Log("Speed effect applied");
}
public override void End()
{
Debug.Log("Speed effect ended");
}
}
When I call the AddEffect method I pass a new instance of SpeedEffect (I think it's an instance) as the parameter and then in the AddEffect method I call the Activate method from it, however, in the SpeedEffect class, it doesn't have or override that method so I'm assuming it goes to the base class which does have it and continues and now here's where I get confused in the Activate method it calls the ApplyEffect method, but how does it know to call the one in the SpeedEffect class?
Despite not having an override for Activate() that method still exists in the SpeedEffect class, you just didn't need to write any code for it since its the same code so theres no need to duplicate it.
The code for Activate() calls the ApplyEffect() method for whatever class its being called from. In this case: EffectBase.Activate() and SpeedEffect.Activate() have the same code in terms of reading it, but they are not the same; EffectBase.ApplyEffect() and SpeedEffect.ApplyEffect() are two different methods and each are called from their respective classes.
Is there any way to listen to notificstions(read their text) shown in notificstion bar in Xamarin?
I know that in AndroidStudio, we can use NotificationListenerService, but I can not find any Xamarin alternative.
Real example:
I recieve a Whatsapp message and get notified, I want my app to check if the message was sent by Emily- if so, do something...
Thanks for help and replies
Xamarin.Android has a framework wrapper for Android.Service.Notification.NotificationListenerService.
[Register ("android/service/notification/NotificationListenerService", DoNotGenerateAcw = true, ApiSince = 18)]
public abstract class NotificationListenerService : Service
{
~~~
}
Just as in Java, it is an abstract class that you need to implement.
public class MyNotificationListenerService : NotificationListenerService
{
public override void OnCreate()
{
base.OnCreate();
}
public override void OnNotificationPosted(StatusBarNotification sbn)
{
~~~~
}
public override void OnNotificationRemoved(StatusBarNotification sbn)
{
~~~~
}
}
I am not sure how to decide about how to refactor some production code. This code works as select records top 1 from db and decided to column containing value under the below.
switch(column_value):
case send_email:
send_email.DoIt();
case enable_somexx:
enable_somexx.DoIt();
case response_email:
response_email.DoIt();
Showing the below examples, there are created classes for every events (records) including a DoIt() method(SendMail, DecideMail, ResponseMail, MailXXX, enable_somexx). The classes include 3 subfolders actions named action, decision, response (actually these classes irrelevant which other because code select top 1 record)
I'm thinking of refactoring this code logic like this:
Create base class named Behaviour
other 3 main classes will inherit from this base class
Code:
public abstract Behaviour
{
public virtual void DoIt(string type) {
}
}
--Also another classes Decision, Response will inherit from Behaviour.
public class Action : Behaviour
{
override void DoIt(string type) {
}
}
public class Email : Action
{
override void DoIt(string type)
{
if(type == SEND)
call_sendmethod
else if(xxx_operation_about_mail)
call_xxx_operation_about_mail
}
}
But I cannot handle (actually I don't like my solution because I don't want to create same class every operations like EmailAction, EmailResponse, EmailDecision or another operations)
If you make this code block refactoring, how would you do it?
Thank you.
Using your idea of refactoring ... this is how I would code it:
Here is an outline:
Create an abstract class for Behavior
Create an action class which inherits Behavior
Then you can code like this to trigger desire "action".
Notice how I override the "Send" behavior to customize it to "special sent".
Here is the fiddle: https://dotnetfiddle.net/m3tjWl
Blockquote
public class Program : Action
{
public static void Main()
{
Console.WriteLine("Hello World");
var command = Console.ReadLine();
//trigger send from Action class
Action x = new Action();
x.DoIt(command);
//trigger send from behavior class
//the lines below are added to show how you can still access the parent behavior, remove or use where appropriate
Behaviour y = x;
y.Send();
}
}
public abstract class Behaviour
{
public virtual void Send()
{
Console.WriteLine("sent");
}
public virtual void EnableX()
{
Console.WriteLine("enabled");
}
public virtual void Reply()
{
Console.WriteLine("replied");
}
public abstract void DoIt(string type);
}
public class Action : Behaviour
{
public override void DoIt(string type)
{
if(type.ToUpper() == "SEND")
this.Send();
else if (type.ToUpper() == "ENABLEX")
this.EnableX();
else if (type.ToUpper() == "REPLY")
this.Reply();
else
Console.WriteLine("Unknown Command");
}
new public void Send()
{
Console.WriteLine("Special Sent");
}
}
I have a Xamarin-Objective C binding project (see here: https://github.com/bbhsu2/XamarinAdMarvelBinding). Fundamentally, it works and I can load clickable ads.
So I implement the AdMarvelDelegate interface on my ViewController class, but important implemented methods are not getting called:
public class CategoryViewController : UITableViewController, IAdMarvelDelegate
{
/*Initializing stuff*/
public void GetAdSucceeded() //not called
{
Console.WriteLine("succeeded!");
}
public void GetAdFailed() //not called
{
Console.WriteLine("failed!");
AppDelegate.Shared.AddAdBanner();
}
}
Does anyone have any suggestions on why GetAdSucceeded and GetAdFailed are not called? In the binding project I have:
[Export("getAdSucceeded")]
void GetAdSucceeded();
[Export("getAdFailed")]
void GetAdFailed();
which I believe are correct
If the corresponding members in AdMarvelDelegate are optional (i.e. they don't have the [Abstract] attribute in the binding), you'll need the [Export] attribute on those methods:
public class CategoryViewController : UITableViewController, IAdMarvelDelegate
{
[Export ("getAdSucceeded")]
public void GetAdSucceeded()
{
Console.WriteLine("succeeded!");
}
[Export("getAdFailed")]
public void GetAdFailed()
{
Console.WriteLine("failed!");
AppDelegate.Shared.AddAdBanner();
}
}
I know that C# does not offer multiple inheritance. And I know there' are workarounds like this one for instance.
But here's a problem that I faced today, can't figure any ELEGANT workaround. I'll add some abstract code-sample so you get it quicker...
(let it be a real-life ASP.NET code - cause those "class A, class B" code-samples are really confusing):
public class AdminPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
}
public class JQueryPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
RegisterJQueryScript();
base.OnLoad (e);
}
}
//now here's what I REALLY miss in C#
public class AdminJQueryPage : AdminPage, JQueryPage;
Compose out the functionality? This is better for Single Responsibility. You'd have to think carefully about your constructors.
interface IAdminPage {
public string AdminPageMethod();
}
interface IJQueryPage {
public string JQueryPageMethod();
}
internal class AdminPage : IAdminpage {
private string someString;
internal AdminPage(string value) {
this.someString = value;
}
public string AdminPageMethod() {
return "AdminPage result with some string: " + this.someString;
}
}
internal JQueryPage : IJQueryPage {
private int someNumber;
internal JQueryPage(int value) {
this.someNumber = value;
}
public string JQueryPageMethod() {
return "JQueryPage result with number: " + this.someNumber;
}
}
class AdminJQueryPage : IQueryPage, IAdminpage {
private readonly IAdminPage adminPage;
private readonly IJQueryPage jqueryPage;
public AdminJQueryPage(string someString, int someNumber) {
this.adminPage = new AdminPage(someString);
this.jqueryPage = new JQueryPage(someNumber);
}
public string AdminPageMethod() {
return this.adminPage.AdminPageMethod();
}
public string JQueryPageMethod() {
return this.adminPage.JQueryPageMethod();
}
}
If you really want multiple inheritance, look at Scala's traits
Edit: added passing of constructor values to composed out classes. Also made the classes internal (cannot be accessed or constructed outside the assembly) because they are only ever constructed by the AdminJQueryPage class, which is the 'public-facing' class.
I came from C++ too and dont miss it, especially since reading Refactoring [and using a non-OOTB tool for that].
You can use PostSharp to post process based on placing attributes on your AdminJQueryPage which would achieve the exact same effect.
Or you can Extract Method code into helper classes and call that (i.e., Joe's example)
Or you can put the helpers in a single base class and call from that.
Either way your code will be clearer.
It's only a matter of time before your mixins start overlapping, and then your general suite of techniques for managing that complexity needs to kick in - in C++, MI should only have been one tool in a suite - rather than a very sexy hammer.
its possible to fake a mixin by specifying a interface and creating extension methods for that interface. however I'm not use this will help overriding methods, only adding new ones. you are of course able to then call an extension method when overriding, but that is basically the same as extracting the methods to a helper class, but with a little more sugar
Even if it was possible, one problem with the semantics of an MI-based solution to the specific problem you raised is what happens on the markup side? The Render() method that generates the markup would run first in one class, and then in the other? That's probably not the behavior you want when both classes generate entire pages.
If you're open to solutions that are outside of the language itself, there are several elegant options in ASP.NET that will address the type of issue you raised (changing the actions taken during an event in the page life cycle). For example:
Page Adapters
Control Adapters
Custom user controls
HttpModules
Master Pages
Tag mapping
The best choice will of course depend on the details of your application. In case it's helpful, I cover those options in my book, including sample code: Ultra-Fast ASP.NET.
The simplest approach is to build a hierarchy - allow AdminPage to inherit from JQueryPage like so:
public class AdminPage : JQueryPage
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
}
public class JQueryPage : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
RegisterJQueryScript();
base.OnLoad (e);
}
}
//now here's what I REALLY miss in C#
public class AdminJQueryPage : AdminPage
My guess is some of this awkwardness comes from the ASP.NET page model, which uses overridden base class methods.
You can to do this with Interfaces
public interface IJQueryPage
{
}
public abstract class AdminPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
protected override void OnLoad(EventArgs e)
{
if (this is IJQueryPage)
{
RegisterJQueryScript();
}
base.OnLoad (e);
}
}
public class AdminJQueryPage : AdminPage, IJQueryPage
{
}