How to make whole android screen (current) unresponsive while processing? - android

I have one activity, which contains header (title bar). This header also contains the image of Sync feature of my app.
As per requirement of client, I want that when the user tap on this button, the animation of this image (button) starts, which is rotating animation (I've achieved this animation). But while this animation is being performed, I want to freeze the whole screen so the user can not tap on other views while sync is in progress.
Till now I've used the following method but with no success :
private boolean stopUserInteractions = false;
public boolean dispatchTouchEvent(int i) {
View v = imgSync;
if (v.getId() == R.list.imgSync) {
System.out.println("UI Blocked...");
return false;
}
else {
return super.dispatchTouchEvent(ev);
}
return false;
}
Can anyone guide me for this? Any trick/snippet or any other hint.
EDIT : I dont want to use ProgressDialog while this sync process is being happening.

Have an OnTouchListener class within your activity, or let your Activity implement OnTouchListener. All children of the activity's layout should set a single object of this if they want to listen touch events. Within listener, check whether you should process the click or not.

Related

How to implement hold and drag feature for multi selection?

Samsung phones have this feature where you can hold your finger on an item then drag it down, i can multi select items quickly like in the gif
Is there any way i can implement this feature in my apps even if it's just for Samsung devices?
Example image
even if it's just for samsung devices
You can implement this feature on any device. I first found this feature in Mi devices.
It is somewhat complicated. But you can use libraries for this purpose like DragSelectRecyclerView.
Add following code to your build.gradle:
dependencies {
implementation 'com.github.MFlisar:DragSelectRecyclerView:0.3'
}
In your java file, add following code:
Create a touch listener.
mDragSelectTouchListener = new DragSelectTouchListener()
.withSelectListener(onDragSelectionListener)
// following is all optional
.withMaxScrollDistance(distance) // default: 16; defines the speed of the auto scrolling
.withTopOffset(toolbarHeight) // default: 0; set an offset for the touch region on top of the RecyclerView
.withBottomOffset(toolbarHeight) // default: 0; set an offset for the touch region on bottom of the RecyclerView
.withScrollAboveTopRegion(enabled) // default: true; enable auto scrolling, even if the finger is moved above the top region
.withScrollBelowTopRegion(enabled) // default: true; enable auto scrolling, even if the finger is moved below the top region
.withDebug(enabled);
Attach this touch listener to the RecyclerView.
recyclerView.addOnItemTouchListener(mDragSelectTouchListener);
On item long press, inform the listener to start the drag selection.
mDragSelectTouchListener.startDragSelection(position);
Use the DragSelectionProcessor, it implements the above mentioned interface and can be set up with 4 modes:
Simple: simply selects each item you go by and unselects on move back
ToggleAndUndo: toggles each items original state, reverts to the original state on move back
FirstItemDependent: toggles the first item and applies the same state to each item you go by and applies inverted state on move back
FirstItemDependentToggleAndUndo: toggles the item and applies the same state to each item you go by and reverts to the original state on move back
Provide a ISelectionHandler in it's constructor and implement these functions:
onDragSelectionListener = new DragSelectionProcessor(new DragSelectionProcessor.ISelectionHandler() {
#Override
public Set<Integer> getSelection() {
// return a set of all currently selected indizes
return selection;
}
#Override
public boolean isSelected(int index) {
// return the current selection state of the index
return selected;
}
#Override
public void updateSelection(int start, int end, boolean isSelected, boolean calledFromOnStart) {
// update your selection
// range is inclusive start/end positions
// and the processor has already converted all events according to it'smode
}
})
// pass in one of the 4 modes, simple mode is selected by default otherwise
.withMode(DragSelectionProcessor.Mode.FirstItemDependentToggleAndUndo);
You can see a demo activity here.
Is there any other library for the same purpose?
Yes, you can also use Drag Select Recycler View by afollestad. And you can see practical implementation for afollestad's Drag select Recycler View here.

PanGestureRecognizer inside ListView (Xamarin.Forms)

I'm making a messaging app in Xamarin.Forms (Android and iOS).
Messages are being shown in a ListView.
Now I want to add a new feature. When I drag the message balloon to the side, it shows the message info.
The user holds the message, drags to right or left.
If he drags enough, a new page with the info shows
If he releases before this "threshold", the balloon bounces back to its place.
I tried implementing this with a PanGestureRecognizer (PGR in this context) on the balloon, but it worked partially.
Android
I can drag, release, release before the threshold, and it works! But if I drag vertically while dragging to horizontally, the ListView "steals" the pan gesture, the PGR "forgets" it and doesn't return any event. So the balloon just keeps there, a bit to the side.
-- Initial state.
-- Dragging the message to the right
-- I've already released the message, but it is still to the right.
This doesn't happen if I release the finger without dragging down.
It may look obvious: "Why don't you just make it go back when the finger is "forgotten"?"
Because when the problem happens, it doesn't generate another event. (And the ListView doesn't have the Scrolled event as the ScrollView)
iOS
When I try to use the PGR, the ListView doesn't work. But the side drag works. Looks like the PGRs are grabbing the pan gesture always first.
Is there any way to make the PGR and the ListView work simultaneously?
For iOS you can try adding:
Application.Current.On<iOS>().SetPanGestureRecognizerShouldRecognizeSimultaneously(true)
References: https://github.com/xamarin/Xamarin.Forms/issues/2299#issuecomment-399578363
https://learn.microsoft.com/ru-ru/xamarin/xamarin-forms/platform/ios/application-pan-gesture
For Android i made a workaround with timer:
private System.Threading.Timer timer;
private void PanGesture_PanUpdated(object sender, PanUpdatedEventArgs e)
{
var statusType = e.StatusType;
if (statusType != GestureStatus.Started && timer == null)
{
// after gesture was broken down, next event will be with wrong
// status, like the gesture is continues. So, reset status to Started,
// consider it is new gesture:
statusType = GestureStatus.Started;
}
var slidingView = yourView;
switch (statusType)
{
case GestureStatus.Started:
// do any initializations..
timer = new System.Threading.Timer(_ => {
finishTranslation(slidingView);
});
break;
case GestureStatus.Running:
{
// do any animations..
timer.Change(TimeSpan.FromMilliseconds(100), TimeSpan.Zero);
}
break;
}
}
private void finishTranslation(View slidingView)
{
timer = null;
// finish your animation
}
But problem with tap gesture still here((

Android partially active Activity

I have an activity A. I am creating a kind of tutorial for user for this activity, to teach him how he can use the app on that screen.
For that, my requirement is :
I want to blur all the views of the activity except one view. I want to prompt user to click on that view through a hand image pointing at that view.
Nothing should happen if the user clicks on the blurred/greyed out area, but if he taps on that particular active view, it should react to that touch.
I was thinking of using a full screen fragment for this. The Fragment will take the following input from the activity :
for what coordinates, is should not blur the screen and pass the touch event to the activity
the coordinates on which it should show that pointing hand image.
After from these coordinates, the fragment background would be blur.
I wanted to confirm if that's possible, to make the fragment partially active, i.e. delegate it's touch events to the activity for a particular view of the activity.
Also, please let me know if there is any other better approach of achieving the same thing.
Edit1 :
Thinking of using a fragment here, because I'd want this type of behaviour on different screen in future. In that case, I'd make that fragment generic which takes some inputs (as described above) and use it on different screens.
There's a very good library called SCV which does what you're trying to achieve, you're able to customize the styles for it too. I've used this for first time the app is opened to show the user a tutorial.
According to their Github
The ShowcaseView (SCV) library is designed to highlight and showcase specific parts of apps to the user with a distinctive and attractive overlay. This library is great for pointing out points of interest for users, gestures, or obscure but useful items.
Further Reading:
Android Arsenal - Showcase Views Tutorial
ShowCaseView on Android - Indipendev
I found it much easier to include an 'extra' layout around the UI of my activity, and then to add a highest-z grey mostly-transparent filter to it and put the instructions on that.
Each "step" of the instructions was a different layout that was dynamically loaded into that layout container as they clicked. (Just another approach)
The 'container' layout is a: FrameLayout
then in my Activity I have: (ignore bad naming)
private void addOverlayLayout() {
frameLayout = (FrameLayout) findViewById(R.id.framelayoutInner);
frameLayout3 = (FrameLayout) findViewById(R.id.framelayout3);
frameLayout3.setBackgroundColor(Color.DKGRAY);
frameLayout3.setAlpha(0.3f);
// Dynamically create a relativelayout which will be appended to framelayout
relativeLayout = new RelativeLayout(getApplicationContext());
relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams
.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
instructionOverlays.add(createSimpleClickInstruction(R.layout.instruction_reader_1));
instructionOverlays.add(createSimpleClickInstruction(R.layout.instruction_reader_2));
if (FullscreenReaderActivity.isFirstRun) {
displayNextGuide();
}
}
public void displayNextGuide() {
// clean relative layout if it has views
relativeLayout.removeAllViews();
// clean frame layout if it has child (safe if empty)
frameLayout.removeView(relativeLayout);
if (!isFirstRun) {
return;
}
if (instructionOverlays.size() > 0) {
runOnUiThread(instructionOverlays.get(0));
instructionOverlays.remove(0);
} else {
frameLayout3.setBackgroundColor(Color.TRANSPARENT);
frameLayout3.setAlpha(1.0f);
}
}
public Runnable createSimpleClickInstruction(final int resource) {
return new Runnable() {
#Override
public void run() {
getLayoutInflater().inflate(
resource,
relativeLayout,
true
);
relativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
displayNextGuide();
}
});
frameLayout.addView(relativeLayout);
}
};
}

Can I make a button appear disabled and still listen for clicks?

I'd like to gray out a button so it appears disabled to the user, but still listen for clicks so that I can display a message to the user that explains why the button isn't applicable.
I'd like to ensure that the Android API is the one configuring whatever is the appropriate standard disabled appearance as opposed to manually setting the button color to gray, etc. What's the best way to do this?
Related: Android - Listen to a disabled button
this is custom button which expose the event of touch when disabled
it working for sure, and tested. designed specific to you
public class MyObservableButton extends Button
{
public MyObservableButton(Context context, AttributeSet attrs)
{
super(context, attrs);
}
private IOnClickWhenEnabledListner mListner;
public void setOnClickWhenEnabledListener(IOnClickWhenEnabledListner listener) {
mListner = listener;
}
private interface IOnClickWhenEnabledListner {
public void onClickWhenEnabled();
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (!isEnabled() && mListner != null) {
mListner.onClickWhenEnabled();
}
}
return super.onTouchEvent(event);
}
}
this is the right way to accomplish what you want from my point of view as android developer.
there is no problem extanding all android's views, and use them on the xml files, and source instead..
good luck
You could also manually set the background of your Button to the default one for disabled. But leave the button enabled and handle the click events in the normal fashion
something like this should do it:
mBtn.setBackgroundResource(android.R.drawable.btn_default_normal_disabled);
I am not an Android expert, so there could be better ways, but what about disabling the button and overlaying a transparent view that will catch the events?
You could have the view always there laying below the button so you just need to change a z-index, or create it dynamically when needed.
If your button is on the newer types that controls color via backgroundTint rather then background, this is what you should do:
if (enabled) {
ViewCompat.setBackgroundTintList(btn, getResources().getColorStateList(R.color.button_states)); // either use a single color, or a state_list color resource
} else {
ViewCompat.setBackgroundTintList(btn, ColorStateList.valueOf(Color.GRAY));
}
// make sure we're always clickable
btn.setEnabled(true);
btn.setClickable(true);
You could also set the Button's style to look grayed out (for both pressed and non-pressed states), then setOnClickListener() as normal, but have the onClick() method give the message that it isn't clickable.
Since button extends textview. You may use the methods in textview such as .setTextColor() or .setBackgroundColor() .
Now for the the display you have 2 options:
AlertDialog - displays an alert but doesn't self close unless specified.
Toast - displays a text over a given time and self closes.
take your pick.

Create a Button glSurfaceView in Android

I'm having a bit of a problem with this. I wanted to make a push button. However, I don't know how to use the Button class with OpenGL. I am not using the "R" class within Java instead I am using the old "assets" folder for compatibility.
I have it setup to find if you have touched the button and on "touch up" load the next screen. The flaw in this is that you can touch the screen and then drag your finger over to the button and then lift your finger. The next screen will load, because it has registered the touch up event at that position.
The easiest way to fix this would be to use the Button class, but how do I use it (especially because I won't be able to use findViewById)?
This is the code I was using but when onTouchUp check for a collision touchDown has magically changed to be the same as TouchUp?
private void onTouchDown(Vector2 point)
{
if (test.justUp)
{
test.setTouchDown(point);
test.justUp = false;
}
}
private void onTouchUp(Vector2 point)
{
test.setTouchUp(point);
test.justUp = true;
if(OverlapTester.pointInRectangle(test.bounds, test.touchUp) &&
OverlapTester.pointInRectangle(test.bounds, test.touchDown))
{
game.setScreen(new LevelSelect(game));
return;
}
}
When creating your own button class, register the "touch down" position and the "touch up" position. If they've both been registered inside your button graphic area, the button is pressed.

Categories

Resources