I have an activity and 10 fragments which I draw on activity. All fragments on activity need to have "drag to refresh". I add Swipe Refresh Layout to create it. Now when I click on the switch, all is fine; but when I try to drag it from one stage to another, swipe to refresh appears, and the switch is just staying in the same position. So how can I block the refreshing of the swipe refresh layout on time when the user drags the switch from one position to another?
I tried to make it like this:
onOffSwitchSettings.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
((MainActivity) getActivity()).swipeContainer.setRefreshing(false);
return false;
}
});
But how can I turn it on after?
According to SwipeRefreshLayout reference:
The SwipeRefreshLayout will notify the listener each and every time
the gesture is completed again; the listener is responsible for
correctly determining when to actually initiate a refresh of its
content. If the listener determines there should not be a refresh, it
must call setRefreshing(false) to cancel any visual indication of a
refresh. If an activity wishes to show just the progress animation, it
should call setRefreshing(true). To disable the gesture and progress
animation, call setEnabled(false) on the view.
You've forgotten to use ((MainActivity)getActivity()).swipeContainer.setEnabled(false) method.
Another problem is that using above you're going to disable SRL permanently, so you need to enable it again when the action is right, I mean there's no more dragging.
Hope it will help
Related
I have class "myButton" that inherits from class "Button". Inside implemented method "onTouch", which works if you press the button. And I need to perform actions when you click wherever outside the button.
Is there any way to verify that the touch was made outside the button?
I came up with the idea to add a touch check to the View (full screen). But in this case, if you click on the button, two events "onTouch" will be activated: inside my class "myButton" and clicking on View.
If you want to handle the push down and release on a button you can just do
Button button = (Button) findViewById(R.id.button);
button.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// PRESSED
break; // if you want to handle the touch event
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL
// RELEASED
break; // if you want to handle the touch event
}
return false;
}
});
this will handle if a button is pushed down and if a button is released and if you just want pushed you can change accordingly
You have kotlin and java both tagged this is java so if you want it in kotlin just let me know
ps im returning false because if you dont you will circumvent the button's regular touch processing. Which means you will loose the visual effects of pressing the button down and the touch ripple. Also, Button#isPressed() will return false while the button is actually pressed.
I have a RecyclerView which have EditText as its list items. When i scroll the RecyclerView, the EditText loses focus when the item goes off screen. So the focus does not remain on the EditText when it comes back on the screen on scroll.
I want the focus to remain on the same item. For that i also tried storing position of the item on focus and reassigning the focus in onBindViewHolder. But that slow downs the scrolling.
I also tried this with ListView but there is another kind of focus related problem. Focus jumps there.
Have searched for this lot on SO and Googled a lot. but always found answers like android:focusableInTouchMode="true" and android:descendantFocusability="afterDescendants" which does not work.
Any help would be highly appreciated.
The whole point of a RecyclerView is to reuse the views so that the phone doesn't have to keep all the rows in memory at once and doesn't have to be constantly destroying and creating views. When your EditText leaves the screen, the phone takes that view, resets its contents and moves it to the bottom of the incoming view stack.
This means that once your EditText leaves the screen it no longer exists. It cannot keep focus because it is removed from the layout.
The only way around this would be what you mentioned, which is storing the position, checking when that position comes onscreen, and manually restoring focus.
As Elan Hamburger wrote, we should store the position and restore it when an item appears on screen after scrolling.
A problem is we don't know when the item appears and disappears. When we have several ViewHolders, onBindViewHolder can even not be invoked again. In this case we should use onViewAttachedToWindow and onViewDetachedFromWindow to learn when the item appears and disappears on screen.
private var focusPosition: Int = -1
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
super.onBindViewHolder(holder, position)
// Choose right ViewHolder and set focus event.
holder.edit_text.onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
focusPosition = position
}
}
override fun onViewAttachedToWindow(holder: ViewHolder) {
super.onViewAttachedToWindow(holder)
// Your condition, for instance, compare stored position or item id, or text value.
if (holder.adapterPosition == focusPosition && holder is SomeViewHolder) {
holder.edit_text.requestFocus()
}
}
//override fun onViewDetachedFromWindow(holder: UinBillViewHolder) { //
// super.onViewDetachedFromWindow(holder)
//}
Try use the next:
LinearSnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
It helped me when using GridLayoutManager with Vertical orientation.
This option scrolls the list a little on its own so that when scrolling, the edge of the next items in the RecyclerView becomes is visible, so the focus is not lost.
But this does not help if you need to scroll too quickly (if the column did not have time to load, and you need to scroll further).
I found the answer here Scrolling recyclerview from the middle item
I have many ScrollViews with RelativeLayouts inside in one Activity all of them cover the whole screen. I got buttons in some of them but the problem is the top layout is blocking the click events for the other layouts.
I want it so if no button is hit at the first layout it passes the click event to next etc.
You may wonder why i have many layouts that covers the whole screen and that is because i got scrollviews in them to create a 3D paralax effect scrolling background with different layers.
On the top layer also have setOnDragListener if that is important.
Here i will try to show you how my setup is:
HorizontalScrollView1--Layout1--Images/Buttons
HorizontalScrollView2--Layout2--Images/Buttons
HorizontalScrollView3--Layout3--Images/Buttons
So right now ScrollView3 is taking all clicks because its in the front/top. I can't disable clicks on the Scroll cut it needs to be scrollable and there is also buttons at the top layer that needs to be clickable.
overriding this in the relativelayout and returning true makes the above routine redundant:
RelativeLayout slideLayout=new RelativeLayout(mContext){
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mIsMuteTouches) return true;
return super.onInterceptTouchEvent(ev);
}
};
I have a ListView with a significant number of items on it. I would like to figure out a way to get it to scroll to a certain position, but have that position be at the very top of the view.
The other issue is that the ListView gets invalidated and re-drawn at some point after this happens and I need it to return to this position when it is re-drawn.
I have tried smoothScrollToPosition, but this only brings the item into the view, and does not place it at the top. I have tried scrollTo(x,y) but I don't know the exact y-position of the item in the view. I have tried setSelection and setSelectionFromTop, but the selection gets reset when the view is invalidated. I have also tried all of these things within a post(Runnable) call, with no luck.
Here is the solution I have at the moment, which is awful.
listView.post(new Runnable() {
#Override
public void run() {
listView.smoothScrollToPosition(10000);
listView.smoothScrollToPosition(pos);
}
});
This forces it to scroll down to the bottom and scroll back up until the item at the specified position comes into the view, which has the effect of placing it at the top. Fortunately, the animation only goes so far as to scroll from the top to the end position, so it doesn't actually play out scrolling to the bottom and then back up. However, this solution is slow, hacky, and just generally awful. Does anyone have a better one?
I would like to capture all motion events from the screen using a listener for example if i do a swipe on a screen from top to bottom there will be a touch down, touch move and a touch up. Since this touch will be over multiple views example linear view, buttons and text fields i tried to attach on touch listeners to all views but i would get bad data for example i would get touch up without touch downs and so on. Please advise a way that will achieve this.
A good way to handle this is to attach the OnTouchListener to the parent ViewGroup (layout) of all your views.
For example a RelativeLayout that have multiple views (linear view, buttons and text fields) as you mention in your question. You can do like that:
RelativeLayout currentView = (RelativeLayout) findViewById( R.id.MyRelativeLayout );
currentView.addView(aSubView);
currentView.addView(aSubButton);
currentView.addView(aSubTextView);
currentView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// Here you will receive all the motion event.
return false;
}
});
You can override the dispatchTouchEvent(MotionEvent ev) method in you activity.
It's called before the MotionEvent is forwarded to the different Activity Views.
You can then do what you want with it, forward them, consume them...