onFocusChange including children? - android

Assume that I have a simple full-screen ConstraintLayout, with a few EditTexts and TextViews in the middle.
Is it possible to know whether one of those views is in focus? What I'm trying to achieve is basically a blanket onFocusChangeListener for all children of a layout.
I've tried assigning a listener to the ConstraintLayout, but it only fires if I tap on the layout itself, outside of those EditTexts.
I could simply assign a listener for each individual element in the UI, but what if I have hundreds?
(I could simply loop through all of them, but please assume I can't)

You could attach a global listener to your ViewTreeObserver with addOnGlobalFocusChangeListener. Something like:
view.getViewTreeObserver().addOnGlobalFocusChangeListener(
new OnGlobalFocusChangeListener() {
#Override
public void onGlobalFocusChanged(View prevFocus, View newFocus) {
// Do stuff here
}
}
);

Related

How to delegate click event from parent (ViewGroup) to child (View) android?

You can, of course, assign onclick to all child views through a loop, but is there such an opportunity to hang the click event on the parent element, and then receive the event on the desired child view, as, for example, in html/js through the event target?
You can setup an onClickListener() for the parent and then inside that you can delegate the click using child.performClick(). if you cant to know more, you can reference https://developer.android.com/reference/android/view/View.html#performClick()
The code would look something like this:
parent.setOnClickListener {
child.performClick()
}

How can I remove OnClickListeners from RecyclerView's ViewHolders when they are disposed?

I am using RecyclerViews in my app project and setting OnClickListeners with their ViewHolders (in their constructors like mentioned in a StackOverflow Q&A).
Then I have this question: how can I remove OnClickListeners from RecyclerView's ViewHolders when they are disposed.
Usually, we can remove an OnClickListener by doing this:
view.setOnClickListener(null);
And if it is a ViewPager's PagerAdapter, we can do so in destroyItem method.
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = container.findViewById(R.id.viewId);
view.setOnClickListener(null);
}
Where can I do so with RecyclerView? --Or, I need not do so?
If you want to null set the onCLickListener() of the views of RecyclerView.Adapter when the view goes off the screen, you can do so by overriding the http://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onViewDetachedFromWindow(VH) in your recyclerView's adapter. You will receive the holder as parameter that has just gone off the screen. You can null set onClickListener of any view available in that holder.
Or if you just want to do the same when it becomes visible on the screen, you can do in onBindViewHolder(). But this does not make sense as instead you can avoid setting listener.
Points to remember, related to this answer:
Setting the listener to null may be ther requirement when you do not want to set click listener to view for every data set but to only few. In this case, it is always better to set listenrs to null as and when they go off the screen. Otherwise, as RecyclerView will re-use (recycle) the holder objects that were gone away to represent the new dataset that is becoming visible. In this process, data set (view in a holder) that you did not set the listener to may have the listener set because of recycling.
All in all, while getting the advantage of smooth scrolling due to recycling, it is dev's responsibility to reset the views (clearing image views, text views etc..) and null setting the onCLickListener etc.
If you are using RecyclerView and binding OnClickListeners to it's every row root view, there is no need to dispose them.
But if some views shouldn't respond to click event's just use setOnClickListener(null)

Android: How to update state of one view based on the state of other

I am facing this issue for which the solution might just be a simple one, but my tries have not succeeded.
I have a parent view container which contains three child views which have their on onClick event handlers declared and perform different actions.
What I am trying to do is add statelist drawables to each of these so that for different states the colors of the child views change.
This is what it looks like roughly -
Child View 3 has it own statelist and works independently and I have what I need.
However, what I want is the state of child view 1 and 2 should change simultaneously when the state of either is changed while they perform their independent actions on click. So basically, if I am pressing (pressed state) child view 1 which changes its color maybe, the same should happen for 2 as well and vice versa. All this while, child view 3 should be unaffected.
I tried a number of ways to workaround with statelist drawables but with no success. Can anyone please help me out with this issue?
I believe there should be some elegant way to handle this in Android.
Thanks!
How about to implement an interface, kinda:
OnStateChangeListener() {
onStateChanged(int color, int whatever);
}
for both of related views and to listen each other state changing.
If you refer all this to be done directly in your drawable, it is not possible.
I am sure there are other ways but three on a first glimpse:
You may use a RadioGroup and then use
RadioButton instances
this will require default RadioButton style changes
You can create a custom view container (derived from LinearLayout for example) and then add logic in it to deal with clicks from its child views
use RadioGroup source as a reference how Google did it
You can use GreenRobot EventBus or any other bus to dispatch an event from your clicked view and any other views can listen and change their own states
you can create a function like this-
public void setStates(View views[],int clickedViewID){
for(int i=0;i<views.length;i++){
if(views[i].getID==clickedViewID){
//change color
}
else{
// do whatever like chnage color.
views[i].
}
}
}
pass all the three child views and the id of the clicked view.
Here than you can check the id of the three view if it is matched than change the color of that only otherwise anyhting else for all other views.

Only relayout children and not all the tree

I'm trying to recreate ListView (and AbsListView) logic, with view recycling.
I need this but we can say it's only for understand Android logic.
Suppose my children items are the same (same layout), using fixed height RelativeLayout.
During scrolling, I'm reusing ghost children view and set properties for current item.
It's working fine, since I'm using View.offsetTopAndBottom() and invalidate() instead of requesting layout during scroll for optimization.
My problem is updating the children (RelativeLayout).
Depends of item, I want to hide or show ImageView on this item. For that, I'm just using iconImage.setVisibility( GONE ) and iconImage.setVisibility( VISIBLE ).
Since I'm blocking requestLayout, it seems to be setVisibility() does not work properly.
If I use requestLayout, all the tree will measure and layout itself, and it's not a good way for a scrolling user experience.
Is there a way for only request layout on recycle child item ?
You need to notify your listView with changed of view so call notifyDataSetChanged(); from Uithread like this :
final ArrayAdapter adapter = ((ArrayAdapter) getListAdapter());
runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
}
});

Scroll to form element

I have a form with lots of fields and when I press the "submit" button, I'd like the scrollview to jump to the position where the unanswered field is located. Is there a method other than scrollto(x,y) to do this or such coordinates must always be mapped to the form's elements somehow ( something like (form element).getCoordinates() )?
Thanks
This should work -
view.setFocusableInTouchMode(true);
view.requestFocus();
view.requestRectangleOnScreen(viewRectangle);
You can always take a look at the View class.
P.S. The unanswered field will be selected but I'm not sure that if it is out of the screen the Activity will scroll to the requested position.
ScrollViews do have predefined methods scrollTo() & scrollBy() for such functionality.
I believe you are having issues in getting co-ordinates. So I suggest store height of each view (that consumes vertical space)by using View.getHeight method & store heights in a Map collection .
Below is the code snippet I tried
scrollView.post(new Runnable() {
public void run() {
Integer emailTextViewHeight = (Integer)hashMap.get("EmailTextViewHeight");
scrollView.scrollBy(0, emailTextViewHeight);//scrolls to emailTextView
}
});

Categories

Resources