I have a Button 'Remove' on a View, lets call it UserInputView. UserInputView is added to a Layout by user input. Now, the user may have typed something wrong, and wants to press the Remove-button I've created, to remove this particular UserInputView.
I've added an EventHandler for the Click-event of the Remove-button. Now I need to find what View-object this particular Button belongs to so I can call _myLayout.RemoveView(theViewICantFind). How do I find this View-object? I can't seem find it by any properties of the Button in question.
Or perhaps, is it another clever way of removing the UserInputView from the Layout that I don't know about?
Thanks folks!
In your EventHandler, there is a sender object. That is the actual View object.
I suppose you could remove it like this in the Click handler:
public void MyButtonHandler(object sender, EventArgs args)
{
var button = (Button)sender;
_myLayout.RemoveView(button);
}
If you want to remove the view the Button belongs to, you can just get it by calling button.Parent.
Related
What I want to achieve:
I want to get the button text as parameter for the function
What I want:
// Operators - setOnClickListener
btnDivide.setOnClickListener { viewModel.mountOperator(it.text) }
btnMultiply.setOnClickListener { viewModel.mountOperator(it.text) }
btnMinus.setOnClickListener { viewModel.mountOperator(it.text) }
btnPlus.setOnClickListener { viewModel.mountOperator(it.text) }
What is working:
// Operators - setOnClickListener
btnDivide.setOnClickListener { viewModel.mountOperator(btnDivide.text) }
btnMultiply.setOnClickListener { viewModel.mountOperator(btnMultiply.text) }
btnMinus.setOnClickListener { viewModel.mountOperator(btnMinus.text) }
btnPlus.setOnClickListener { viewModel.mountOperator(btnPlus.text) }
The problem that is appearing:
Error: Unresolved reference: text, when i am doing it.text
But inside setOnClickListener{ it: View! }, I saw this preview as it is generally shown. So I thought that, here it is refering to the button to which I am setting the onClickListener.
if there is any confusion about the question, please write in the comment. If my approach is wrong, share in the comments
So I thought that, here it is referring to the button to which I am setting the onClickListener.
Here, it is of type View and not of type Button, or whatever type of specific view type you want it to be, so because not all views have a text property (which means that View doesn't have something called text, but Button might), you can use something like this:
btnDivide.setOnClickListener { viewModel.mountOperator((it as Button).text) }
where you can replace Button with whatever type of view it is.
it as Button is casting the View we get into our specific type, in your case I'm assuming this will be a button, but you can cast it to whatever type of view it actually is.
it: View! here does refer to the button you're setting the onClickListener to, but it's returned to you as a View and not of a more specific type
Also to follow up on #a_local_nobody's answer, the reason it's just passing in a generic View and not the type you're setting the click listener on, is because you can create a single listener object/function and reuse it for all the things that need to handle clicks (which could be different subclasses of View)
So if you like, you could make one of those and use it instead of repeating the code for each button:
fun handleButtonClick(view: View) {
if (view is Button) viewModel.mountOperator(view.text)
}
btnDivide.setOnClickListener { handleButtonClick(it) }
// or as a function reference
btnMultiply.setOnClickListener(::handleButtonClick)
And another thing you can do when you're assigning multiple identical click listeners (or doing the same anything to a bunch of things) is to just do a loop
listOf(btnDivide, btnMultiply, btnMinus, btnPlus).forEach {
it.setOnClickListener { //bla bla }
}
that works for reusing a function reference or just creating a new one for each listener (like you're doing in your question) - it just saves you repeating yourself, it can be easier to read, and if you need to make changes you only have to do it in one place
I have a standard LinkMovementMethod established in my TextView to push a web Activity of some sort when the user touches a link. However, I want to establish a "do you want to see the link" dialog rather than taking the user straight to the webpage. I've tried overriding the touch methods but it all gets a little convoluted. A little help?
You can accomplish it in two ways:
Create custom Spans: more complicated, but you can accomplish more customised text consisting of clickable parts (or bold, differently coloured etc). To know more, check out ClickableSpan and SpannableStringBuilder
Extend LinkMovementMethod to accept custom click listener
In my opinion second solution is better in basic cases like yours. Here is how you can do it:
Copy this java class: InternalLinkMovementMethod to your project
Add set the link movement method of your TextView to this custom one, providing a click listener:
OnLinkClickedListener clickListener = new OnLinkClickedListener() {
#Override
public boolean onLinkClicked(String linkText) {
// here you can handle your click, eg show the dialog
// `linkText` is the text being clicked (the link)
// return true if handled, false otherwise
}
}
yourTextView.setMovementMethod(new InternalLinkMovementMethod(clickListener));
I have sort of a file manager. It displays files in a ListView. Each of those ListViews has a custom footer - a button, which is defined in a xml file. Pressing a button allows user to chose a file from the "downloads" directory and copy it to the folder where the button was pressed. This is implemented through the AlertDialog. So by clicking the option from the dialog I get a path of a file that should be copied.
Now, how do I get the location from which my button was pressed? Can I somehow pack some sort of data in my button on its creation so that later when it is pressed I could identify its initial location?
there are many ways to achieve that. you can create a separate OnClickListener for each button as JaLoveAst1k proposes. you could also add some information to the buttons's tag (setTag()) and get it back in the onClick() function. Yet another way would be to have a Hashtable<Button, String> where you store your string informaton relative to the Button.
Yes, like this:
protected class CustomListener implements View.OnClickListener {
private String text;
public CustomListener(String text) {
this.text = text;
}
...
}
And set this listener to button, in constructor give data.
In my application I have a list of questions stored in an ArrayList, and I want to display a dialog that shows one question, and then continues to the next one after the question is answered. The way that I'm currently doing it (iterating through a loop) hasn't been working because it just layers all of the dialogs on top of one another all at once which causes a host of other issues. What I'm looking for is a way to still iterate through the questions, but just change the layout of the dialog each time until it has finished each question in the list. Can anyone give me a good pointer for how to get this going?
You can make a function that takes title and message as parameters and shows a dialog.
showDialog(String title, String message){ // Show dialog code here}
Within that dialog's answer button's listener call another function (showQuestion(currentQuestion)) that iterates the arrayList till it is over
int currentQuestion=0;
ArrayList<QuestionObject> questionList;
showQuestion(int i){
if(i<questionList.size()){
showDialog(questionList.get(i).getTitle,questionList.get(i).getMessage);
currentQuestion++;
}else{
//quiz is over
}
}
I assume you mean that you just want to change 1 single layout(created within XML i.e main.xml). In order to do this, make sure that the class your working on is pointing to that layout. From there (assuming your using an Event listener for when the user submits an answer) you can change do as you want by the following:
TextView txt = (TextView) findViewById(R.id.textView); // references the txt XML element
and in your Event listener, if the answer is correct then change(Have i be a global variable thats initially set to 0).
if(i<arrayList.size()){
txt.setText(arrayList.get(++i));
}else{
txt.setText("You Finished");
}
From there, in the else statement, you can change arrayLists and reset i to 0;
If you are trying to use the positive, neutral, and negative buttons; then you may have problems with multiple dialogs. Try defining a customized layout with your own TextViews, ListViews, and Buttons. You can implement listeners and everything else like a regular layout. Then just pass your customized layout to the dialog through AlertDialog.Builder.setView().
PS If you include code examples of what you are currently doing we can provided answers that are less vague.
This is week one of Android for me!
I'm programmatically creating a textview, two labels and a button in the same activity.
The idea is that the textview receives a string from the user.
The user clicks the button and the textview string is passed to a proc which returns a string result, and the string result is assigned to one of the labels.
public void onClick(View view) {
sresults = showPP(ttsymbol.getText().toString().trim());
}
But this doesn't work, because "the final local variable sresults cannot be assigned, since it is defined in an enclosing type"
I think I understand what is going wrong, but is there an alternative way of returning the results so that they can be displayed in the label? Or is it necessary to create a new dialog inside the onClick function to show them?
Thanks!
If you are sure of changing the value of sresults, then there is no point in making it final. final is used for constant values. You should directly set the value to the label view. The label view reference can be final.
public void onClick(View view) {
label.setText(ttsymbol.getText().toString().trim());
}
More code would be helpful here, how is sresults, showPP, etc defined? However, the message suggests you have defined sresults as "final" which means you can't change the value. Probably removing final would solve that problem.