I know how to prevent double-clicking on a component. What I want to know if there is some way to avoid this behaviour "by default" when adding a component. Do I have to go every single item that can be clicked in an app and write the same code for every single component?
I know I could subclass, say, Button class, write the code for preventing double-clicking there, and only use my Button class in the app. What is the point of it? Why isn't something like that in the default Android Button class? I haven't seen any intended double-clicking behaviour in ANY app. Do I have to write a subclass of every single View that is susceptible of being clicked in order to prevent this? is there something I am missing?
Just to clarify, my question is about something like disableDoubleClick() method or something like that. I already said I know how to prevent this, but is a bit of a hassle to do it for every single clickable item in an app.
You can use Kotlin with its extensions in conjunction with reactive bindings of RxJava.
for the general view it will look something like:
fun View.clickWithDebounce(debounceTime: Long = 600L, action: () -> Unit): Disposable =
RxView.clicks(this)
.debounce(debounceTime, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { action() }
Use it like this:
button.clickWithDebounce{
//do stuff
}
textView.clickWithDebounce{
//do other stuff
}
imageView.clickWithDebounce{
//do some completely unrelated with the previous two stuff
}
floatingButton.clickWithDebounce(100000000){
//do some stuff and wait 100000 seconds before the next click
}
For more info: Kotlin Extensions, RxJava RxBinding
Hope it helps.
Related
I've been using rxjava2 for a while but mostly kind of a boilerplate, I didn't clearly know its features.
I supposed to create a search Edittext which call method after sometime. I got it working by the following code:
RxTextView.textChanges(edittextSearch)
.filter(charSequence -> charSequence.length() > 3)
.debounce(800, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(string -> {
search(string.toString());
}, error -> {
Log.e("ERROR","ERROR LISTENING: " + error.getMessage());
});
However, I need one more feature for this EditText, which is as soon as I type, even with just one character, I would display an "X" icon to clear the input, or hide it if user manually delete all text.
I don't know if the textChanges method above could do that or I have to add another text watcher for the edittextSearch
Thank you for your time.
You can achieve what you want by using a TextInputLayout and adding app:endIconMode="clear_text". It's part of the material design library, there are plenty of guides on how to use them.
This will automatically add a clear icon when the user begins typing, clicking the icon will clear the text and update your textChanges observable.
I'm using SelectionTracker form the support-library-v28
It works great, just as expected.
Only thing I need, is to enable Select All feature (using the ToolBar)
Looking at the API, I see that there is one way to select all, but that one requires creating Iterable<Long> with all the values, meaning, create an array which hold Long values from 1 to datasource.size()
Is there any simpler way to select all the items in my datasource?
Seeing as I've recently had to set up the same sort of functionality, I thought I'd share my approach. Using the setItemsSelected(Iterable<K> keys, boolean selected) method really isn't as complex as it seems.
Yes, you will need to pass in an iterable. What I did was, loop through my data and store the index of each item as a 'long' inside of an arrayList().
EX:
yourData.forEachWithIndex { i, item ->
//Be sure to start at one, just plus one
someOtherTempArray.add(i.toLong() + 1)
}
Then I created a method that makes it easy to 'trigger' the select all functionality:
EX:
private fun startHandler(isChecked: Boolean){
val handler = android.os.Handler(Looper.getMainLooper())
val runnable = Runnable {
kotlin.run {
mTracker!!.setItemsSelected(someOtherTempArray.asIterable(),
isChecked)
}
}
handler.post(runnable)
}
The 'isChecked' parameter, which will essentially determine if we want to select all or deselect all.
Note that I am simply using my arrayList of 'keys' (for me this is just the index of the item. However, this may differ depending on how you have your ItemDetails Builder set up) and calling the Kotlin .asIterable() function to turn it into an iterable.
I have also placed the call to setItemsSelected() inside of a handler to force the selection to take place on the UI thread.
Now whenever you want to select/deselect all, you can call the startHandler(true)!
I'm experimenting a little bit with RxJava, and I have stuck in a what sounds to be a simple task.
Let's say we have two Views, View1 and View2.
Right now I'm trying to accomplish that, when View1 is visible, the View2 needs to be gone.
P.S. I'm searching for RxJava solution.
Edit 2
As I mentioned in comment, I was trying to use RxView.visibility().
So therefor I did not publish any code, because none of it worked and it's mostly one line.
As for the down voters, at least try to mention what you don't like about the question, so I could improve it.
Try:
RxView.layoutChangeEvents(view1)
.subscribe(ignore -> {
if (view1.getVisibility() == View.VISIBLE) {
view2.setVisibility(View.GONE);
} else {
view2.setVisibility(View.VISIBLE);
}
}, throwable -> new Exception(throwable));
I don't really understand what you're trying to do in your experiments, I think in your case you don't need RxJava, it's usual if/else condition, but I've thought this small example, which maybe helps you.
I have only EditText and Button as Views:
RxTextView.textChanges(editText)
.map(text -> !TextUtils.isEmpty(text))
.subscribe(RxView.visibility(button));
It'll show the button only if user inputs some text.
Here's a better solution if you're using RxBinding library using the RxView's visibility() function:
view2.visibility(View.GONE).accept(view1.getVisibility() == View.VISIBLE);
Using two-way Android Databinding, is it possible to have a generic inverse boolean converter? For example, I would like to do something like this:
<Switch android:checked="#={!viewModel.myBoolean}" />
When I run this in Android, the switch just rapidly fires back and forth. I tried to create a two way binding app:inverseChecked following some examples from George Mount, but I was not successful (just kept getting error stating cannot find event 'inverseCheckedAttrChanged' on View type 'android.widget.Switch').
As a comparison, using Aurelia this just works as you would expect for two way binding. In WPF, probably the first converter you make is some sort of InverseBooleanConverter to easily tackle these sorts of things. So, am assuming I am just missing something obvious here.
I actually didn't expect it to work at all. I assume, it's switching back and forth all the time, because the bindings don't apply inverse function of your binding expression.
That said, I tested the behavior with the current data binding library version and checked the generated sources. With the simple example of android:checked these show notes how the inverse should look like and apply it appropriately.
Also George Mount wrote a Blog post about it a short while ago: https://medium.com/google-developers/android-data-binding-inverse-functions-95aab4b11873
If you try to implement an app:inverseChecked, you'd also have to implement a #BindingAdapter("inverseChecked") as setter, #InverseBindingAdapter(attribute="inverseChecked") as getter and #BindingAdapter("inverseCheckedAttrChanged") for setting up the change listener.
The latter could look like the following:
#BindingAdapter("inverseCheckedAttrChanged")
public static void setupInverseCheckedAttrChanged(Switch view, InverseBindingListener listener) {
OnCheckedChangeListener newListener = null;
if (listener != null) {
newListener = (v,b) -> listener.onChange();
}
view.setOnCheckedChangeListener(newListener);
}
I have an image which I am processing, and I have two buttons, undo and redo. I need the code to undo/redo previous touch action if either of those two buttons are clicked. I know I have to use a stack. How should I implement it?
There are two main patterns for implementing Undo/Redo:
The "memento" pattern.
The "command" pattern.
1. Memento Pattern
The idea of the memento pattern is that you can save a copy of the entire internal state of an object (without violating encapsulation) to be restored later.
It would be used (for example) like this:
// Create your object that can be "undone"
ImageObject myImage = new ImageObject()
// Save an "undo" point.
var memento = myImage.CreateMemento();
// do a bunch of crazy stuff to the image...
// ...
// Restore to a previous state.
myImage.SetMemento(memento);
2. Command Pattern
The idea of the command pattern is to encapsulate the actions that are actually performed on an object. Each "action" (or, "command") can optionally know how to roll itself back. Alternatively, when a rollback needs to occur, the entire chain of commands can be executed again.
It would be used (for example) like this:
// Create your object that can be "undone"
ImageObject myImage = new ImageObject()
// Create a "select all" command
var command = new SelectAllCommand(myImage); // This does not actually execute the action.
// Apply the "select all" command to the image
selectAll.Execute(); // In this example, the selectAll command would "take note" of the selection that it is overwriting.
// When needed, rollback:
selectAll.Rollback(); // This would have the effect of restoring the previous selection.
It all depends what your touch events do in the first place. You have to abstract what your application does in response to the touches into a class that you can fill a Stack with. Then, the stack implementation is easy.
If it's image manipulation, it might take up too much memory to keep a whole stack of Bitmaps around. You'll probably get the infamous OutOfMemoryException after pushing two or three items onto your stack. What you'd probably be better off doing is abstract the actions available in your app and rebuilding on undo/redo. You're basically creating a stack of instruction sets. This makes it slower the larger your stack is, but if the images in memory are large it might be the only way to do it.
In the newer Android versions (22+) you could use a Snackbar. Here's small code fragment for listener:
public class MyUndoListener implements View.OnClickListener{
&Override
public void onClick(View v) {
// Code to undo the user's last action
}
}
and creating a message at the bottom of the screen for an "undo" action:
Snackbar mySnackbar = Snackbar.make(findViewById(R.id.myCoordinatorLayout),
R.string.email_archived, Snackbar.LENGTH_SHORT);
mySnackbar.setAction(R.string.undo_string, new MyUndoListener());
mySnackbar.show();