Visual Studio / Xamarin OnClickListener - android

I'm new to programming, so I apologise if this is a stupid question!
I'm building an app in VS15/Xamarin, and am trying to set an onClickListener, however it keep stelling me there is an error "The type name 'OnClickListener' does not exist in the type 'View'".
I've tried a number of solutions, but clearly I'm missing something!
This is my code:
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
namespace MyStory
{
[Activity(Label = "MyStory", MainLauncher = true, Icon = "#drawable/Books")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
Button btn_Short = FindViewById<Button>(Resource.Id.btn_Short);
Button btn_Flash = FindViewById<Button>(Resource.Id.btn_Flash);
Button btn_Poet = FindViewById<Button>(Resource.Id.btn_Poet);
Button btn_About = FindViewById<Button>(Resource.Id.btn_About);
btn_About.SetOnClickListener(new View.OnclickListener())
{
#override
public void onClick(View v)
{
startActivity(new Intent(MainActivity.this, About.class));
}
}
}
}
}
This is what the screen looks like:
screenshot

C# is not java.Try something like this:
btn_About.Click += myCustomClick;
Then outside your oncreate:
public void myCustomClick(object o, EventArgs e) {
//handle click here
}
But check the syntax.
If you want it your way you should make your activity implement View.IOnClickListener like this:
public class MainActivity: Activity, View.IOnClickListener
{
//code here
}

Question was asked very long ago but I found it and so may others. Hope this helps somebody.
Xamarin has its newances and using += EventHandler has its dangers. Firstly you must be sure to unregister this handler at the end of the object's lifecycle as otherwise it will cause memory leaks. Using Androids ClickListener is really a better solution. In Xamarin you can do something like this
public class TEditClickListener : Java.Lang.Object, View.IOnClickListener
{
private RelayCommand _command;
public TEditClickListener(RelayCommand command)
{
_command = command;
}
public void OnClick(View v)
{
_command?.Execute(null);
}
}
and then instantiate this class and use View.SetOnClickListener method to register it. This way there surely won't be memory leaks.

Related

.init(activity); is showing error [android]

i am trying to implement ShineButton in my project . I have successfully synced the library to the gradle and added shine button in the xml.
now when i am trying to write the java code
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b1 = (Button)findViewById(R.id.button);
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), "Kill bill", Toast.LENGTH_SHORT).show();
}
});
ShineButton shineButton = (ShineButton) findViewById(R.id.po_image2);
shineButton.init(context);
}
}
.init(activity); is showing cannot resolve symbol activity.
You don't literally copy the code verbatim, you read the documentation and object types supported by the method.
public void init(Activity activity) {
For example, I assume you are running that from an activity based on the usage of findViewById? Then you need "this instance of the Activity"
shineButton.init(this);
or an instance of an Activity if you were in a Fragment
shineButton.init(getActivity());
If the code is in Activity use shineButton.init(Activityname.this).
If it is in
fragment use shineButton.init(getActivity()).
Read this: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/ and this https://developer.android.com/training/index.html
Change:
shineButton.init(context);
To:
shineButton.init(MainActivity.this);
MainActivity.this holds the instance of MainActivity class and can be used to initialise the view.

when the .jar contains EventBus module

I have to bind a (.jar) file which contains an Eventbus module. When I call it vs reported an exception: XXXActivity has no public methods called onEvent.
but in reality the activity had an onEvent method.
Can help me?
Here is my code!
[Activity(Label = "BaseActivity")]
public class BaseActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
//EventBus.Default.Register(this);
try
{
JMessageClient.RegisterEventReceiver(this.Application.ApplicationContext);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(" ==ex==" + ex.Message);
}
// Create your application here
}
public void onEventMainThread(CN.Jpush.IM.Android.Api.Event.MessageEvent Event)
{
System.Diagnostics.Debug.WriteLine(" ==1==");
}
...
}
IMRecActivity
[Activity(Label = "IMRecActivity")]
public class IMRecActivity : BaseActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
}
public void onEvent(CN.Jpush.IM.Android.Api.Event.MessageEvent Event)
{
// CN.Jpush.IM.Android.Api.Event.MessageEvent me = (MessageEvent)Event;
CN.Jpush.IM.Android.Api.Model.Message msg = Event.Message;
switch (msg.ContentType.ToString())
{
case "text":
TextContent textContent = (TextContent)msg.Content;
System.Diagnostics.Debug.WriteLine(" ==JMessage OnEvent==" + textContent.Text);
break;
default:
System.Diagnostics.Debug.WriteLine(" ==JMessage OnEvent==" + msg.Content);
break;
}
System.Diagnostics.Debug.WriteLine(" ==JMessage OnEvent==");
}
}
JMessageClient.RegisterEventReceiver(this.Application.ApplicationContext); this used to register an EventBus in the .JAR.With the code,you can see that I have declare onEvent method,but it not working.
By the way,I already uesed a tool like jd-gui to see how it work.
Here is the way to download the .JAR file:
https://www.jpush.cn/downloads/sdk/android/
The Official website,which is a Chinese website.
https://www.jpush.cn/common/products
I would recommend investigating the respective .jar using a tool like jd-gui(http://jd.benow.ca/) to see what the expected method visibility is. You can then use respective Metadata fixes to resolve any issues you find there after the generated binding is created.
I've created a generic guide to help out with this task in which you can look into:
https://gist.github.com/JonDouglas/dda6d8ace7d071b0e8cb

Prevent closing by hardware back button in xamarin forms on android

I want to prevent closing the app by pressing the hardware back button in xamarin forms on android.
I want, that you can navigate with the hardware back button in the app (what is working), but do not want to exit, when the first page in navigation stack is reached.
I tried to use the OnSleep event in xamarin forms, but here I can not cancel the exit.
I also tried catching the back button in android:
public override void OnBackPressed()
{
//base.OnBackPressed();
}
But when using xamarin forms, I do not know which page is currently showing. So I do not know if the navigation back is allowed or not
It works with evaluating the NavigationStack (when you use NavigationPage).
In my Activity, I override the OnBackPressed
public override void OnBackPressed()
{
if(App.Instance.DoBack)
{
base.OnBackPressed();
}
}
In my xamarin forms app (App.Instance (it is a singleton)), I will evaluate the NavigationStack of the current Page like this.
public bool DoBack
{
get
{
NavigationPage mainPage = MainPage as NavigationPage;
if (mainPage != null)
{
return mainPage.Navigation.NavigationStack.Count > 1;
}
return true;
}
}
When there is only one page left in the NavigationStack I will not call base.OnBackPressed, so that I will not close the App.
![test]
And here's what the code could look like for a Xamarin Forms MasterDetail page scenario...
public bool DoBack
{
get
{
MasterDetailPage mainPage = App.Current.MainPage as MasterDetailPage;
if (mainPage != null)
{
bool canDoBack = mainPage.Detail.Navigation.NavigationStack.Count > 1 || mainPage.IsPresented;
// we are on a top level page and the Master menu is NOT showing
if (!canDoBack)
{
// don't exit the app just show the Master menu page
mainPage.IsPresented = true;
return false;
}
else
{
return true;
}
}
return true;
}
}
Just give a blank call in the page where do you wanna prevent, like
protected override bool OnBackButtonPressed()
{
return true;
}
This will prevent the back button in XF-Droid.
Expanding Chris's answer as there is no App.Instance now and one cannot access App in a static manner within platform code.
1. App.xaml.cs in the Shared project
public bool DoBack
{
get
{
return MainPage.Navigation.NavigationStack.Count > 1;
}
}
2.MainActivity.cs in the Android project
Declare a variable in the class:
App app;
In OnCreate(Bundle bundle) change LoadApplication(new App()); to:
app = new App();
LoadApplication(app);
Override the OnBackPressed() method:
public override void OnBackPressed()
{
if (app.DoBack)
{
base.OnBackPressed();
}
}
Here is a solution that works on Android.
Introduce a counter in the application class and increment it with each OnStart and decrement it with each OnStop this way when the counter is 1 you'll know you are at your last activity.
Needless to say, use a base activity implementation so that you don't have to copy-past boiler plate code.
The solution proposed can work nicely, but I don't like "static property exposure" to solve problems. More over, I don't like the usage of "properties as methods" solutions, especially when a lot of logic is involved.
The main problem here how we can handle the OnBackButton() method from our Xamarin.Forms.Application class.
What about doing the same thing in a more elegant way?
First you need to extend the Xamarin.Forms.Application class like this:
namespace YourNameSpace
{
public class Application : Xamarin.Forms.Application
{
#region Public Methods
public bool HandleBackButton()
{
return OnBackPressed();
}
#endregion
#region Application Methods
protected virtual bool OnBackPressed()
{
return false;
}
#endregion
}
}
Your App implementation now will use this class as base class. Remember to modify your xaml and your xaml.cs accordingly:
<common:Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:common="clr-namespace:YourNameSpace"
x:Class="YourNameSpace.App">
</common:Application>
In your App.cs implementation you can now override the OnBackButton() method.
public partial class App : YourNameSpace.Application
{
#region Constructors
public App()
{
InitializeComponent();
}
#endregion
#region App Methods
protected override bool OnBackPressed()
{
// Handle when the back button is pressed
return false;
}
#endregion
}
Then you need to change a little your Activity class implementation.
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
#region Constants and Fields
private App _app;
#endregion
#region Activity Methods
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
_app = new App();
LoadApplication(_app);
}
public override void OnBackPressed()
{
if(!_app.HandleBackButton())
base.OnBackPressed();
}
#endregion
}
You can use this nuget
chd.hwBackButtonManager nuget
github project

android one button share another java use

If I want to design a button that all java can use it without need to write it in every java,
what should I do?
For Example:
I design a Button.OnClickListener function to search bluetooth devices.
but another java also need to use this Button.OnClickListener function,
I don't want to write same way on two java.
ledWrite.xml:
<Button android:id="#+id/btnScan" />
<ToggleButton android:id="#+id/tBtnWrite" />
bluetoothUtils.java
// Intent request codes
private static final int REQUEST_CONNECT_DEVICE = 1;
private Button button_scan;
button_scan = (Button)findViewById(R.id.button_scan);
button_scan.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
scanbt();
}
});
private void scanbt(){
Intent serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
}
then I design LedWrite.java:
private ToggleButton digitalOutBtn; //LED On/OFF
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ledwrite);
digitalOutBtn = (ToggleButton)findViewById(R.id.tBtnWrite);
digitalOutBtn.setOnClickListener(new OnClickListener()
public void onClick(View v){
if(digitalOutBtn.isChecked()){ //sendMessage("D1"); }
else{sendMessage("D0";}
}
How can I use button_scan in LedWrite.java?
If you want to call a method defined is some other Activity on press of a button, then you can make that method as static.
Let's assume that you have a method named searchBluetooth() in MainActvity and you want to call it from SecondActivity.
Define searchBluetooth() in MainActvity like,
public static void searchBluetooth()
Call this method from SecondActivity like,
MainActivity.searchBluetooth()
If you don't want to use static because of memory consumption then try with inheritance.
Create a class CommonActivity which extends Activity class
class CommonActivity extends Activity
{
// here define your searchBluetooth method
public void searchBluetooth()
{
// your code here
}
}
If you want to make use of it in Second Activity then
class SecondActivity extends CommonActivity
{
// here you can access `searchBluetooth()` method
}
enclosure a BluetoothListener class?
public BluetoothListener implements OnClickListener {
#Override
public void onClick(View v) {
do something you want...
}
}
then invoke the class in two different class, eg,
button.setOnClickListener(new BluetoothListener());
I recently started learning android and this answer may have some error, if so, please let me know, Thanks.

Is Robolectric able to assert that methods have been invoked?

I've got a button defined in my layout as follows :
<Button
android:id="#+id/speakButton"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="#string/speak"
android:onClick="speak"
/>
The onClick binds to a method in my activity, such as :
public void speak(View v)
{
// Do my stuff here
}
Using Robolectric, I'm able to create a simple test class for that activity, I'd like to know if its possible that I could have a test that invokes the button, and ensures the method in my activity was invoked OK.
(I've got a whole bunch of buttons throughout my app, so intending to have tests to ensure they are wired up correctly, unless anyone has any suggestions as to why I shoudln't bother)
#RunWith(RobolectricTestRunner.class)
public class MyActivityTest
{
private MyActivitymActivity;
private Button speakButton;
#Before
public void setUp() throws Exception
{
mActivity = new MyActivity();
mActivity.onCreate(null);
speakButton = (Button) mActivity.findViewById(com.jameselsey.apps.androidsam.R.id.speakButton);
}
#Test
public void testButtonsVisible()
{
assertThat(speakButton.getVisibility(), equalTo(View.VISIBLE));
}
#Test
public void buttonsInvokeIntendedMethods()
{
// Unsure how to implement this test
}
}
I've never used them but I believe you can do this with the TouchUtils class. Here is a link to the Android TouchUtils docs. In particular you should look at the clickView method.

Categories

Resources