Reputation: 5276
My fragment has a Reset button that clears some EditTexts and puts default values in others. When this happens, focus goes to the last EditText that was given a default value (and sometimes makes the screen scroll). I would like no focus to change. Is there a way to prevent focus change while the screen is resetting?
EDIT:
As requested, here is a sample of my layout file which demonstrates how views are organized (full file was 700+ lines). All EditTexts are nested like these examples. Notice that my EditTexts are nested either 1 or 2 layers within the RelativeLayout within the ScrollView. Therefore, for their common parent, they are grandchildren or great grandchildren.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<!-- So that it will scroll if in landscape mode -->
<ScrollView
android:id="@+id/scrollview_new_grade"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<!-- my main layout frame -->
<RelativeLayout
android:id="@+id/rel_lay_new_grade"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginTop="-4dp" >
<!-- Multiple instances like this -->
<LinearLayout
android:id="@+id/linlay_avg_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tv_grade_calc_prompt"
android:layout_centerHorizontal="true"
android:orientation="horizontal" >
<EditText
android:id="@+id/et_grade_calc_cur_grade"
android:layout_width="95dp"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_weight="0"
android:ems="10"
android:text=""
android:gravity="center_vertical|right"
android:inputType="numberDecimal"
android:maxLength="7" />
</LinearLayout>
<!-- 2 instances like this -->
<LinearLayout
android:id="@+id/linlay_weight_other_categories"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/linlay_weight_input"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:gravity="bottom"
android:orientation="horizontal" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent" >
<EditText
android:id="@+id/et_grade_calc_other_categories"
android:layout_width="95dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_gravity="right"
android:ems="10"
android:text="100"
android:gravity="center_vertical|right"
android:inputType="numberDecimal"
android:maxLength="7" />
</RelativeLayout>
</LinearLayout>
<!-- 1 radio group like this (options with EditTexts) -->
<RadioGroup
android:id="@+id/radioGroup1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/tv_grade_calc_prompt"
android:layout_below="@id/splitline_horz6"
android:layout_marginLeft="-8dp"
android:layout_marginTop="10dp" >
<LinearLayout
android:id="@+id/linlay_radio_group_0"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- stuff -->
<EditText
android:id="@+id/et_grade_calc_target"
android:layout_width="85dp"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_weight="0"
android:gravity="center_vertical|right"
android:inputType="numberDecimal"
android:maxLength="7"
android:width="70dp" />
</LinearLayout>
</RelativeLayout>
</ScrollView>
Upvotes: 0
Views: 727
Reputation: 13932
I would take all the views that currently are on screen, and get the view that currently has focus.
Update to reflect your XML
Update Revised Again After taking a deeper look at the XML Something like:
// Hold a reference to the id
int childIdWithFocus = 0;
// Your main Layout which is the first item of your scroll view
ViewGroup parentViewGroup = (ViewGroup) getView().findViewById(R.id.rel_lay_new_grade);
// Then get count of all views
int childCount = parentViewGroup.getChildCount();
// Then using the Views count
for(int i = 0; i < childCount; i++){
// Check if the child elements are ViewGroups
if(parentViewGroup.getChildAt(i) instanceof ViewGroup){
ViewGroup innerParent = (ViewGroup) parentViewGroup.getChildAt(i);
int innerParentCount = innerParent.getChildCount();
// Loop through inner view groups
for(int j = 0; j < innerParentCount; j++){
// Check for nested ViewGroups
if(innerParent.getChildAt(i) instanceof ViewGroup){
// Again get the childCount of the ViewGroup
ViewGroup childInnerViewGroup = (ViewGroup) innerParent.getChildAt(i);
int childCountOfInnerParentView = childInnerViewGroup.getChildCount();
for(int k = 0; k < childCountOfInnerParentView; k++){
// Now check for EditText since we are in another level
if(innerParent.getChildAt(k) instanceof EditText){
EditText currentEditText = (EditText) innerParent.getChildAt(k);
boolean isFocused = currentEditText.isFocused();
if(isFocused){
childIdWithFocus = currentEditText.getId();
return;
}
}
}
}
}
}
}
// Then sometime after refreshing your view
EditText childWithFocus = (EditText) findViewById(childIdWithFocus);
childWithFocus.requestFocus();
The biggest problem with this method
Directly from Android Docs:
public final boolean requestFocus ()
Added in API level 1 Call this to try to give focus to a specific view or to one of its descendants. A view will not actually take focus if it is not focusable (isFocusable() returns false), or if it is focusable and it is not focusable in touch mode (isFocusableInTouchMode()) while the device is in touch mode. See also focusSearch(int), which is what you call to say that you have focus, and you want your parent to look for the next one. This is equivalent to calling requestFocus(int, Rect) with arguments FOCUS_DOWN and null.
Returns Whether this view or one of its descendants actually took focus.
Hope this helps. If you are using dynamic views and do not have an xml file with all the EditText's you will have to wait until after your entire view has been created before getting the child count because it would return 0 by default since this parent layout would know nothing about dynamic views.
Upvotes: 1
Reputation: 3667
You could save which EditText, or which UI control currently has focus in the onSaveInstanceState, and then use the savedinstance object to restore the focus to that control when the screen is restoring the UI.
Which method is used for restoring the instance is different for activities than for fragments. With Activities it's onRestoreInstanceState, and with Fragments you use onActivityCreated.
Remember to make sure that in the onActivityCreated method in your fragment, that you check that the passed instanceState Bundle is not null first before accessing it, since the instanceState is only created when creating Fragment the initial time, or when re-creating the Fragment.
Upvotes: 0