I want to set a listener for ExpandableList. I have searched around but found only android specific following code. How can I convert the following android code to Xamarin.
ExpandableList expListView; // suppose it is initilized
expListView.setOnGroupExpandListener(new IOnGroupExpandListener() {
int previousItem = -1;
#Override
public void onGroupExpand(int groupPosition)
{
if (groupPosition != previousItem)
expandableList.collapseGroup(previousItem);
previousItem = groupPosition;
}
});
You can implement the interface ExpandableListView.IOnGroupExpandListener on the Activity (or Fragment) or as a separate Java-based object.
Activity Example:
public class MainActivity : Activity, ExpandableListView.IOnGroupExpandListener
{
~~~
ExpandableListView expListView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
expListView.SetOnGroupExpandListener(this);
}
~~~
public void OnGroupExpand(int groupPosition)
{
// implement your onexpand code
}
~~~
}
Separate Class:
public class MyExpander : Java.Lang.Object, ExpandableListView.IOnGroupExpandListener
{
public void OnGroupExpand(int groupPosition)
{
// implement your onexpand code
}
}
Related
Ok so I am running a BroadcastReceiver:
public class SyncServiceBroadcastReceiver : BroadcastReceiver
{
public static string syncStarted = "SyncRuns";
private readonly PendingOrdersActivity pendingOrdersActivity;
public SyncServiceBroadcastReceiver(PendingOrdersActivity pendingOrdersActivity)
{
this.pendingOrdersActivity = pendingOrdersActivity;
}
public override void OnReceive(Context context, Intent intent)
{
this.pendingOrdersActivity.RefreshPendingOrdersOnSync();
Toast.MakeText(context, "Datele se actualizează...", ToastLength.Short).Show();
}
}
Each time it hits, I want it to run a method from the activity (method RefreshPendingOrdersOnSync). That's why I've created a constructor which takes in an activity.
In the activity I am registering the BroadcastReceiver, in the OnResume method, by passing in "this":
var filter = new IntentFilter(SyncServiceBroadcastReceiver.syncStarted);
filter.AddCategory(Intent.CategoryDefault);
this.syncServiceBroadcastReceiver = new SyncServiceBroadcastReceiver(this);
this.RegisterReceiver(this.syncServiceBroadcastReceiver, filter);
Still, on the Receiver part, it gives the error from the title....
If I add an empty constructor, I suspect it goes through there and this line in the OnReceive breakes, because this.pendingOrdersActivity is null
this.pendingOrdersActivity.RefreshPendingOrdersOnSync();
I am quite puzzled why
BroadcastReceiver must provide a public default constructor
The default constructor method is required. Because when registering BroadcastReceiver using AndroidManifest.xml, Android uses reflection to instantiate the receiver and it needs a default constructor.
Refer to:https://stackoverflow.com/a/14266261/11083277
If I add an empty constructor, I suspect it goes through there and this line in the OnReceive breakes
I tested a basic demo to test the code, add the default constructor method and the code works fine. The parameterized constructor will be executed. Did you register the receiver in AndroidManifest.xml? If so, try to do the work in code.
[BroadcastReceiver]
public class CustomReceiver : BroadcastReceiver
{
private readonly MainActivity activity;
public CustomReceiver()
{
}
public CustomReceiver(MainActivity activity)
{
this.activity = activity;
}
public override void OnReceive(Context context, Intent intent)
{
activity.method();
}
}
Activity class
public class MainActivity : AppCompatActivity
{
CustomReceiver receiver;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_main);
receiver = new CustomReceiver(this);
}
public void method()
{
...
}
protected override void OnResume()
{
base.OnResume();
RegisterReceiver(receiver, new IntentFilter("package_name"));
}
protected override void OnDestroy()
{
base.OnDestroy();
UnregisterReceiver(receiver);
}
}
I've just started looking into Xamarin and just can not to wrap around my head how to make multiple Activities have a reference same instance of service.
I am starting KeyPressedReceiver from MainActivity and start listening for power button being pressed.
When three click are being made, I am calling service method InitCancelActivity, which starts playing mp3 file and opens CancelActivity.
In CancelActivity there is a text field and a button. And when user press this button, I want the value from text field to be passes to the GeneralService method KillAlert.
The question is how to reference instance of GeneralService (which is already created) from CancelActivity, so I could call KillAlert?
And this part
if (_service == null)
_service = new GeneralService();
looks absolutely wrong. Should I instantiate it in MainActivity and pass to a KeyPressedReceiver constructor?
[Activity(Label = "TTTT", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
KeyPressedReceiver receiver;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
receiver = new KeyPressedReceiver();
RegisterReceiver(receiver, new IntentFilter(Intent.ActionScreenOn));
}
}
[BroadcastReceiver(Enabled = true)]
public class KeyPressedReceiver : BroadcastReceiver
{
private GeneralService _service;
private int _clicks = 0;
public override void OnReceive(Context context, Intent intent)
{
if (_service == null)
_service = new GeneralService();
_clicks++;
if (_clicks > 5)
{
_service.InitCancelActivity();
}
}
}
[Service(Name = "com.ff.GeneralService")]
public class GeneralService : Service {
private readonly Android.Media.MediaPlayer _player;
public GeneralService()
{
_player = new Android.Media.MediaPlayer();
}
public void RaiseAlert()
{
// start playing .mp3 file
}
public void KillAlert(string pass)
{
// stop playing .mp3 file
}
public void InitCancelActivity()
{
this.RaiseAlert();
var i = new Intent(this, typeof(CancelActivity));
i.SetFlags(ActivityFlags.NewTask);
this.StartActivity(i);
}
}
[Activity(Label = "CancelActivity")]
public class CancelActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.cancel);
this.FindViewById(Resource.Id.cancelButtonYes).Click += delegate
{
var password = this.FindViewById(Resource.Id.cancelPassword);
// call KillAlert method from GeneralServic
};
}
}
Create static GeneralService instance and use in Cancel Activity.
for example
[Service(Name = "com.ff.GeneralService")]
public class GeneralService : Service {
private readonly Android.Media.MediaPlayer _player;
public static generalService;
public GeneralService()
{
_player = new Android.Media.MediaPlayer();
generalService=this
}
public void RaiseAlert()
{
// start playing .mp3 file
}
public void KillAlert(string pass)
{
// stop playing .mp3 file
}
public void InitCancelActivity()
{
this.RaiseAlert();
var i = new Intent(this, typeof(CancelActivity));
i.SetFlags(ActivityFlags.NewTask);
this.StartActivity(i);
}
}
and use in CancelActivity like below example
[Activity(Label = "CancelActivity")]
public class CancelActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.cancel);
this.FindViewById(Resource.Id.cancelButtonYes).Click += delegate
{
var password = this.FindViewById(Resource.Id.cancelPassword);
// call KillAlert method from GeneralServic
GeneralService.generalService.KillAlert(password.TEXT);
};
}
}
I'm new in C# Xamarin. I have a sample Java class here (from this tutorial). It's difficult to me to implement ValueEventListener in C# using xamarin.firebase.database. Would you like to help me? Thank you.
public class ChatInteractor implements ChatContract.Interactor {
private static final String TAG = "ChatInteractor";
#Override
public void sendMessageToFirebaseUser(final Context context, final Chat chat, final String receiverFirebaseToken) {
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
databaseReference.child(Constants.ARG_CHAT_ROOMS).getRef().addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void getMessageFromFirebaseUser(String senderUid, String receiverUid) {
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
databaseReference.child(Constants.ARG_CHAT_ROOMS).getRef().addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
First of all: do you have a Xamarin Android Binding for the Firebase Android SDK? If you don't, you can't really follow any Java-Android tutorial, since the Firebase specific classes / interfaces won't exist. If that's the case: install https://www.nuget.org/packages/Xamarin.Firebase.Database/
If you do - implement the interface like that:
(inline implementations - like you can do in java; and it's done in your example - are not supported in C#. So you'll have to create a regular class)
public class MyValueEventListener : Java.Lang.Object, Firebase.Database.IValueEventListener
{
public void OnCancelled(DatabaseError error)
{
throw new NotImplementedException();
}
public void OnDataChange(DataSnapshot snapshot)
{
throw new NotImplementedException();
}
}
and pass it as an eventlistener
DatabaseReference databaseReference = FirebaseDatabase.Instance.Reference;
databaseReference.Child(Constants.ARG_CHAT_ROOMS).Ref.AddListenerForSingleValueEvent(new MyValueEventListener())
What I want to do is basically what was answered here:
how to get html content from a webview?
However, I'm working with Xamarin in C#, and the code given in the top answer is in java. I tried to translate it to C# as follows:
public class LoginWebViewController : Activity
{
WebView localWebView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.WebView);
localWebView = FindViewById<WebView>(Resource.Id.LocalWebView);
localWebView.SetWebViewClient(new JustWebViewClient());
localWebView.LoadUrl(LoginOperations.GetTPLoginUrl());
localWebView.Settings.JavaScriptEnabled = true;
localWebView.AddJavascriptInterface(new MyJavaScriptInterface(this), "HtmlViewer");
}
class MyJavaScriptInterface
{
private Context ctx;
MyJavaScriptInterface(Context ctx)
{
this.ctx = ctx;
}
public void showHTML(String html)
{
Console.WriteLine(html);
}
}
}
But I get the following error:
I tried changing the class to public but it still gives the same error. What is wrong?
Additional code:
public class MyWebViewClient : WebViewClient
{
public override void OnPageFinished(WebView view, String url)
{
base.OnPageFinished(view,url);
Console.WriteLine("DONE LOADING PAGE");
view.LoadUrl("javascript:HtmlViewer.showHTML" +
"('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
}
}
Your constructor is not public and you have to inherit from Java.Lang.Object. You have to add the Export attribute, too.
class MyJavaScriptInterface : Java.Lang.Object
{
private Context ctx;
public MyJavaScriptInterface(Context ctx)
{
this.ctx = ctx;
}
public MyJavaScriptInterface(IntPtr handle, JniHandleOwnership transfer)
: base (handle, transfer)
{
}
[Export("showHTML")]
public void showHTML(string html)
{
Console.WriteLine(html);
}
}
And in your javascript code is an error, too. You are missing a opening ( after showHTML.
view.LoadUrl("javascript:HtmlViewer.showHTML(" + ...
Is the setter injection supported in the Xamarin.forms?
I have a service injected in the bootstrapper like this
Container.RegisterType<ICommonService, CommonService>();
And inside a viewmodel, I want to have an instance injected to a property like this
[Dependency]
public ICommonService CommonService { get; set; }
But in the runtime, the property CommonService is always null.
The attribute I used is the Microsoft.Practices.Unity.DependencyAttribute, not Xamarin.Forms.DependencyAttribute
If I inject inside the constructor, it works
public LandingPageViewModel(INavigationService navigationService, ICommonService commonService)
Edited: added code snippet
public class Bootstrapper : UnityBootstrapper
{
protected override Page CreateMainPage()
{
try
{
return Container.Resolve<Views.LandingPage>();
}
catch (Exception exception)
{
//TODO: intent to get exception info
throw;
}
}
protected override void RegisterTypes()
{
DependencyResolver.Instance.Initialize(Container);
this.RegisterViews();
this.RegisterServices();
this.RegisterSingleton();
}
private void RegisterViews()
{
Container.RegisterTypeForNavigation<LandingPage>();
Container.RegisterTypeForNavigation<Page1>();
}
private void RegisterServices()
{
Container.RegisterType<ICommonService, CommonService>();
}
private void RegisterSingleton()
{
}
}
public partial class App : Application
{
public App()
{
InitializeComponent();
var bootstrapper = new Bootstrapper();
bootstrapper.Run(this);
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
Hmm they removed the DependencyAttribute injection feature since Prism 7.0, I think we should register it manually. (your code snippet should work)
Look: https://brianlagunas.com/whats-new-in-prism-for-xamarin-forms-7-0/