So I am adding new button to my app but when FindViewById is called it returns null and app crashes. In my .cs file I have following function:
void fooUIButtonHandler()
{
var fooUIButton = FindViewById(Resource.Id.fooUIButton);
fooUIButton.Click += delegate
{
if (!CheckOriginalImage())
{
return;
}
Intent intent = new Intent(this, typeof(fooImageDemoActivity));
intent.PutExtra(fooImageDemoActivity.EXTRAS_ARG_IMAGE_FILE_URI,
originalImageUri.ToString());
StartActivityForResult(intent, REQUEST_SB_FOO_UI);
};
}
and my .axml file looks like this:
<Button
android:id="#+id/fooUIButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0b8442"
style="#style/Widget.AppCompat.Button.Borderless"
android:text="foo"/>
I am setting Content View in OnCreate:
SetContentView(Resource.Layout.FooDocumentCreation);
and then calling:
fooUIButtonHandler()
But following line is throwing Null exception:
var fooUIButton = FindViewById(Resource.Id.fooUIButton);
Any ideas how to fix it?
Related
I have the following code in Xamarin.Android, I want to show my main actcivty after the LottieAnimationView finshed.
<com.airbnb.lottie.LottieAnimationView
android:id="#+id/SplashAnimationView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:lottie_autoPlay="true"
app:lottie_fileName="LoadingLottie.json"
app:lottie_loop="false"
app:lottie_speed="1.00"/>
There is an AnimationEnd event in it. So you can try the following code:
LottieAnimationView lottieAnimationView = this.FindViewById<LottieAnimationView>(Resource.Id.SplashAnimationView);
lottieAnimationView.Animation.AnimationEnd += (s, e) =>
{
Intent intent = new Intent(this, typeof(MainActivity));
intent.SetFlags(ActivityFlags.NewTask);
StartActivity(intent);
};
I want to add custom floating spinner. How to add like this ??
I have tried with AutoComplete textview inside TextInputLayout but it's not properly worked.
http://prntscr.com/mm8ksc
//SocietySpinnerLayout.axml
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="50"
android:id="#+id/societySpinnerLayout"
app:errorTextAppearance="#style/ErrorText"
android:theme="#style/CommonTextStyleTheme">
<AutoCompleteTextView
android:id="#+id/societySpinner"
android:paddingBottom="#dimen/padding_20"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#4C5375"
android:textSize="#dimen/textSize_14"
android:hint="SOCIETY"
android:paddingEnd="60dp"
android:textCursorDrawable="#null"
android:inputType="textPhonetic" />
</android.support.design.widget.TextInputLayout>
//SocietySpinner.cs
private void BindToMySociety()
{
//String[] arraySociety = Resources.GetStringArray(Resource.Array.arraySociety);
ArrayAdapter adapter = new SpinnerSocietyAdapter(this, Resource.Layout.PublisherSpinnerItemLayout, HelperNavigation.LstSociety);
_societySpinner.Adapter = adapter;
if (_societySpinner.HasFocus)
{
InputMethodManager imm = (InputMethodManager)GetSystemService(Context.InputMethodService);
imm.HideSoftInputFromWindow(Window.CurrentFocus.WindowToken, 0);
}
_societySpinner.SetOnTouchListener(this);
_societySpinner.Focusable = false;
// _societySpinner.Click+=_societySpinner_Click;
_societySpinner.ItemClick += _societySpinner_ItemClick;
_societySpinner.SetOnDismissListener(this);
if(_selectedSociety!=null)
{
_societySpinner.Text = _selectedSociety.name;
}
}
private void _societySpinner_Click(object sender, EventArgs e)
{
try
{
// _societySpinner.Text = string.Empty;
if (!string.IsNullOrEmpty(_societySpinner.Text))
{
_societySpinner.Text = string.Empty;
_societySpinnerLayout.Typeface = ItalicFont;
_societySpinner.Typeface = ItalicFont;
}
((AutoCompleteTextView)_societySpinner).ShowDropDown();
}
catch (Exception ex)
{
}
}
public bool OnTouch(View v, MotionEvent e)
{
try
{
// _societySpinner.Text = string.Empty;
if (!string.IsNullOrEmpty(_societySpinner.Text))
{
_societySpinner.Text = string.Empty;
_societySpinnerLayout.Typeface = ItalicFont;
_societySpinner.Typeface = ItalicFont;
}
((AutoCompleteTextView)v).ShowDropDown();
return false;
}
catch (Exception ex)
{
return false;
}
}
public void OnDismiss()
{
if(_selectedSociety!=null)
{
if (!string.IsNullOrEmpty(_selectedSociety.name))
{
_societySpinner.Text = _selectedSociety.name;
_societySpinnerLayout.Typeface = RegularFont;
_societySpinner.Typeface = RegularFont;
}
}
else
{
_societySpinnerLayout.Typeface = ItalicFont;
_societySpinner.Typeface = ItalicFont;
}
}
I have tried with above code.But sometime it's throwing out of bound exception.and it's not properly worked.Please give me solution to how to create floating spinner.
I was thinking about this for a long while as I did a similar implementation in one of my earlier projects and then I remembered that I was using the Ganfra Material Spinner to achieve this:
There is a sample project available here
You can use it in XML like below:
<fr.ganfra.materialspinner.MaterialSpinner
android:id="#+id/spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:ms_multiline="false"
app:ms_hint="hint"
app:ms_enableFloatingLabel="false"
app:ms_enableErrorLabel="false"
app:ms_floatingLabelText="floating label"
app:ms_baseColor="#color/base"
app:ms_highlightColor="#color/highlight"
app:ms_errorColor="#color/error"
app:ms_typeface="typeface.ttf"
app:ms_thickness="2dp"
app:ms_hintColor="#color/hint"
app:ms_arrowColor="#color/arrow"
app:ms_arrowSize="16dp"
app:ms_alignLabels="false"
app:ms_floatingLabelColor="#color/floating_label"/>
You can set a hint and a floating label text. If no floating label text is provided, the hint will be set instead.
You use it like a regular spinner, setting an adapter to it:
string[] ITEMS = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6"};
var adapter = new ArrayAdapter<String>(this, Android.Resource.Layout.SimpleSpinnerItem, ITEMS);
adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);
var spinner = FindViewById<MaterialSpinner>(Resource.Id.spinner1);
spinner.Adapter = adapter;
If you need to set an error message, you can do it the same way as an EditText:
// Activate
spinner.Error = "Error";
// Deactivate
spinner.Error = null;
You can choose to have a scrolling animation or to set the error message on multiple lines with the ms_multiline attribute in XML (default is true).
I call a web service which gets 4 files, and while these files are loading I want to show progress to the user (circular or horizontal it doesn't matter). I've followed the examples on internet but nothing appears on screen.
MobileSellReference.Service1 service = new MobileSellReference.Service1();
service.Url = settings.Synchronization.Msellurl;
ProgressBar progressBar = FindViewById<ProgressBar>(Resource.Id.progressBar);
progressBar.Max = 100;
progressBar.Progress = 0;
byte[][] basedataResult = service.ToPPC(basedataZipName, objectId);
progressBar.IncrementProgressBy(25);
byte[][] dutybasedataResult = service.ToPPC(dutybasedataZipName, objectId);
progressBar.IncrementProgressBy(25);
byte[][] tranbasedataResult = service.ToPPC(tranbasedataZipName, objectId);
progressBar.IncrementProgressBy(25);
byte[][] vendbasedataResult = service.ToPPC(vendbasedataZipName, objectId);
progressBar.IncrementProgressBy(25);
I've found a lot of examples using external progressbar libraries but they all want to change the theme of the Activity. Instead I want some simple ProgressBar built into Xamarin.Android. For example when the first file is downloaded I want 1/4 of the circle to be filled, when 2 files are downloaded 1/2 of the circle to be filled et cetera. Similarly for a horizontal ProgressBar.
Use AsyncTask
.axml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="0" />
<ProgressBar
android:id="#+id/pb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal" />
</LinearLayout>
MainActivity:
public class MainActivity : Activity
{
ProgressBar pb;
TextView tv;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
pb = FindViewById<ProgressBar>(Resource.Id.pb);
tv = FindViewById<TextView>(Resource.Id.tv);
UpdatePB uptask = new UpdatePB(this,pb,tv);
uptask.Execute(100);
}
public class UpdatePB : AsyncTask<int, int, string>
{
Activity mcontext;
ProgressBar mpb;
TextView mtv;
public UpdatePB(Activity context,ProgressBar pb,TextView tv) {
this.mcontext = context;
this.mpb = pb;
this.mtv = tv;
}
protected override string RunInBackground(params int[] #params)
{
// TODO Auto-generated method stub
for (int i = 1; i <= 4; i++)
{
try
{
Thread.Sleep(3000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
Android.Util.Log.Error("lv",e.Message);
}
mpb.IncrementProgressBy(25);
PublishProgress(i * 25);
}
return "finish";
}
protected override void OnProgressUpdate(params int[] values)
{
mtv.Text = String.ValueOf(values[0]);
Android.Util.Log.Error("lv==", values[0] + "");
}
protected override void OnPostExecute(string result)
{
mcontext.Title = result;
}
}
}
This might be a helpful link:
https://developer.android.com/reference/android/widget/ProgressBar.html
Code:
<ProgressBar
android:id="#+id/determinateBar"
style="#android:style/Widget.ProgressBar.Horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:progress="25"/>
... and then you just change the progress; 25, 50, 75, 100?
After running into the same problem, I found another solution that got it working. I was reluctant to define a new class (like AsyncTask) to fix this, so looked into async await and threading. I found that after defining an Android.Widget.ProgressBar in an .axml layout file like so:
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="0"
style="?android:attr/progressBarStyleHorizontal" />
I could get it to update if I put the updating tasks in a System.Threading.Tasks.Task.Run and passing in an action that does the updates with RunOnUiThread call like:
btnDoStuff.Click += (sender, e) =>
{
Task.Run(() =>
{
RunOnUiThread(() =>
{
progressBar.Max = 100;
progressBar.Progress = 0;
progressBar.Visibility = ViewStates.Visible;
});
DoSomeWork1(arguments);
RunOnUiThread(() => progressBar.Progress += 25);
DoSomeWork2(arguments);
RunOnUiThread(() => progressBar.Progress += 25);
DoSomeWork3(arguments);
RunOnUiThread(() => progressBar.Progress += 25);
DoSomeWork4(arguments);
RunOnUiThread(() => progressBar.Progress += 25);
});
}
But even then I've had some inconsistent behavior - there may be an element of timing to it as well...
I have been using SaveToString() method to get the source code of the page in WebBrowser Control. But since its been deprecated in Windows 10, Whats the equivalent for SaveToString() in WebView Control of Windows 10.
WebView allows us to invoke script, and we can dump the document.documentElement.outerHTML to do the same thing as SaveToString().
The following shows a very simple sample for your test. Note that I didn't try to make a cool UI design and make all things formatted, but only try to show you the idea.
In xaml:
<StackPanel>
<WebView x:Name="MyWebView" Source="http://www.bing.com" Height="200"
DOMContentLoaded="MyWebView_DOMContentLoaded"/>
<Button x:Name="ViewSourceBtn" Content="View Source" Click="ViewSourceBtn_Click"/>
<RichTextBlock x:Name="SourceBlock" Height="300" >
</RichTextBlock>
</StackPanel>
Code behind:
bool contentloaded = false;
private async void ViewSourceBtn_Click(object sender, RoutedEventArgs e)
{
if (contentloaded)
{
string html = await MyWebView.InvokeScriptAsync("eval", new string[] { "document.documentElement.outerHTML;" });
var paragraph = new Paragraph();
paragraph.Inlines.Add(new Run { Text = html });
SourceBlock.Blocks.Clear();
SourceBlock.Blocks.Add(paragraph);
}
else
{
string err = "Waiting for HTML content to load!";
var paragraph = new Paragraph();
paragraph.Inlines.Add(new Run { Text = err });
SourceBlock.Blocks.Clear();
SourceBlock.Blocks.Add(paragraph);
}
}
private void MyWebView_DOMContentLoaded(WebView sender, WebViewDOMContentLoadedEventArgs args)
{
contentloaded = true;
}
Here is the result by clicking view source button:
I am running in a strange problem. Let me explain:
I am passing set of input data from xml and then using JAXB to parse xml. This java object is then passed to my test method using testng dataprovider.
Here are some related code:
Testdata xml:
<TestData>
<TestDetails>
<testcasename>itemStatusTest</testcasename>
<testcasedetails>App in SUPPRESSED Status</testcasedetails>
<appid>28371</appid>
<status>SUPPRESSED</status>
<marketplace />
</TestDetails>
<TestDetails>
<testcasename>itemStatusTest</testcasename>
<testcasedetails>App in REVIEW Status</testcasedetails>
<appid>22559</appid>
<status>REVIEW</status>
<marketplace />
</TestDetails>
</TestData>
Method which returns object:
private static Object[][] generateTestData(String dataProvider,TestCaseName tcName) throws Exception {
Object[][] obj = null;
try {
JAXBContext jaxbContext = JAXBContext.newInstance(TestData.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
TestData testData = (TestData) jaxbUnmarshaller
.unmarshal(new FileInputStream(new File(dataProvider)
.getAbsoluteFile()));
List<TestDetails> testcaseList = testData.getTestDetails();
obj = new Object[testcaseList.size()][];
for (int i = 0; i < testcaseList.size(); i++) {
if (testcaseList
.get(i)
.getTestcasename()
.equalsIgnoreCase(tcName.testCaseName()))
obj[i] = new Object[] { testcaseList.get(i) };
}
} catch (JAXBException e) {
e.getMessage();
return null;
}
return obj;
}
and my dataprovider:
#DataProvider(parallel = true, name = "TestData")
public Object[][] TestData() {
try {
Object obj[][]= IngestionTestHelper
.generateTestDataForItemStatus(dataProvider);
Reporter.log("Size "+obj.length, true);
return obj;
} catch (Exception e) {
Reporter.log(
"Either XML input is in wrong format or XML is not parsed correctly",
true);
return null;
}
}
Till now everything works like a charm and I am not seeing any issue.
Now i am writing another test method for another test-case. For that I have added following in my exisitng xml like this:
<TestDetails>
<testcasename>itemWorkflowTest</testcasename>
<testcasedetails>Validate workflow for iap</testcasedetails>
<appid>26120</appid>
<status />
<marketplace />
</TestDetails>
Now once i have added this in my existing xml my existing test method is not working. When running I am getting following exception:
java.lang.NullPointerException
at org.testng.internal.Invoker.injectParameters(Invoker.java:1333)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1203)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1197)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1122)
at org.testng.TestNG.run(TestNG.java:1030)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
If i remove the newly added block in xml it starts working.
Please someone help!!!
Well, based on the code, and if I understood correctly :)
When you add the third item the name is different,
You have initialized the Object array with the size of the total number of elements,
obj = new Object[testcaseList.size()][];
But you are adding to the array selectively based on name, so though the init has been done for 3 objects, the data is available only for 2 - this may be causing the NPE..
List<TestDetails> testcaseList = testData.getTestDetails();
obj = new Object[testcaseList.size()][];
for (int i = 0; i < testcaseList.size(); i++) {
if (testcaseList
.get(i)
.getTestcasename()
.equalsIgnoreCase(tcName.testCaseName()))
obj[i] = new Object[] { testcaseList.get(i) };
}