Move layout up when soft keyboard is shown - android

I'm trying to adjust the layout when the soft keyboard appears after an edit text gets focus. Right now if I have many edit text and the keyboard appears, the last edit text are hidden and I can't scroll up.
This is how my layout is builded up:
Template:
<LinearLayout>
<LinearLayout>
// header 1
</LinearLayout>
<LinearLayout>
// header 1
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:orientation="vertical">
// where I inflate view_1
</LinearLayout>
<LinearLayout>
// footer
</LinearLayout>
</LinearLayout>
View (view_1):
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true">
<LinearLayout>
// ...
</LinearLayout>
<LinearLayout>
// ...
</LinearLayout>
<LinearLayout>
<TextView/>
<EditText/>
<TextView/>
<EditText/>
<TextView/>
<EditText/>
<TextView/>
<EditText/>
</LinearLayout>
</LinearLayout>
</ScrollView>
I already try all kinds of combinations of android:windowSoftInputMode (on manifest.xml and programmatically). I tried to set android:isScrollContainer="false" on the scroll view, but nothing.
I also tried this answer, putting an GlobalLayoutListener in my scroll view, but the onGlobalLayout is not called when the keyboard appears. And the isKeyboardShown is always false.

The best solution I found is to add adjustpan property in the activity<> tag in the manifest.xml file .
<activity
android:name="MyActivity"
android:windowSoftInputMode="adjustPan"/>

I ended up doing it my way.
I created a class that implements OnFocusChangeListener to handle all my EditText:
public class EditTextFocusChangeListener implements OnFocusChangeListener {
private ScrollView scrollView;
public EditTextFocusChangeListener(ScrollView scrollView) {
this.scrollView = scrollView;
}
#Override
public void onFocusChange(View view, boolean hasFocus) {
if(hasFocus) {
int left = view.getLeft();
int top = view.getTop();
int bottom = view.getBottom();
int keyboardHeight = scrollView.getHeight() / 3;
// if the bottom of edit text is greater than scroll view height divide by 3,
// it means that the keyboard is visible
if (bottom > keyboardHeight) {
// increase scroll view with padding
scrollView.setPadding(0, 0, 0, keyboardHeight);
// scroll to the edit text position
scrollView.scrollTo(left, top);
}
}
}
}
Then in the activity, I setted the listener for each edit text:
EditTextFocusChangeListener listener = new EditTextFocusChangeListener(mainScrollView);
editText1 = (EditText) findViewById(R.id.editText1);
editText1.setOnFocusChangeListener(listener);
editText2 = (EditText) findViewById(R.id.editText2);
editText2.setOnFocusChangeListener(listener);
...
editTextN = (EditText) findViewById(R.id.editTextN);
editTextN.setOnFocusChangeListener(listener);
And for the last edit text, I setted an EditorAction listerner to handle the 'Done' button on soft keyboard - to hide the keyboard and put the scroll view back to its original position:
editTextN.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
int result = actionId & EditorInfo.IME_MASK_ACTION;
switch(result) {
// user taped on keyboard DONE button
case EditorInfo.IME_ACTION_DONE:
// put the scroll view back to its original position
mainScrollView.setPadding(0, 0, 0, 0);
// hide keyboard
((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);
// remove focus from any edit text
LinearLayout scrollViewLL = (LinearLayout) mainScrollView.getChildAt(0);
scrollViewLL.requestFocus();
break;
}
return false;
}
});
And finally, a way to handle when the user touches outside an edit text to hide the keyboard and put the scroll view back to its original position (found this on web and changed a little to fit my needs):
public void setupUI(View view) {
// Set up touch listener for non-text box views to hide keyboard.
if (!(view instanceof EditText)) {
view.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// put the scroll view back to its original position
if (v instanceof ScrollView) {
v.setPadding(0, 0, 0, 0);
LinearLayout scrollViewLL = (LinearLayout) ((ScrollView) v).getChildAt(0);
scrollViewLL.requestFocus();
}
hideKeyboard();
return false;
}
});
}
// If a layout container, iterate over children and seed recursion.
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
View innerView = ((ViewGroup) view).getChildAt(i);
setupUI(innerView);
}
}
}

This is a late answer, but it may be helpful for anyone that is still looking for an alternative solution. I created a custom ViewTreeObserver.OnGlobalLayoutListener that may fit your use case if you're looking for a way to control the position of the View that you want to ensure is visible when the soft keyboard is shown. Here is a gist to that solution.
The OnGlobalLayoutListener animates changes to the view's translationY property by smoothly moving the view just above the soft keyboard bounds when the keyboard is shown and back to the view's starting position when the the keyboard is dismissed. Let me know if you have any questions on usage.

Put all of your top code in ScrollView, not just view_1. This allows you to move all the parent layout on click by any child EditText.
EDIT: view_1 in this case MUST NOT contains ScrollView!

If you create the Activity using Android Studio Basic Activity wizard (with CoordinatorLayout and theme="#style/AppTheme.NoActionBar"), the default behavior is adjustPan, where the top portion of the activity is push offscreen and the EditText is shown above the Keyboard. You can also change it to adjustResize where the top portion of the activity is maintained.
Edit AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<application ...>
<activity
android:name=".TestInputActivity"
android:label="#string/title_activity_test_input"
android:windowSoftInputMode="adjustResize"
android:theme="#style/AppTheme.NoActionBar">
</activity>
</application>
</manifest>
Keep in mind though the effect and behavior might differ slightly if you are using Scrolling Activity, such as NestedScrollView.
https://code.luasoftware.com/tutorials/android/move-layout-when-keyboard-shown/

android:weightSum="1"
add this

The below code is working for me. Just try this example:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/RelativeAdd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context="com.example.scrollview.MainActivity">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
<EditText
android:id="#+id/editTextUserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp"
android:ems="10"
android:inputType="textPersonName"
android:hint="Name" />
<EditText
android:id="#+id/address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignEnd="#+id/editTextUserName"
android:layout_alignLeft="#+id/editTextUserName"
android:layout_alignRight="#+id/editTextUserName"
android:layout_alignStart="#+id/editTextUserName"
android:layout_below="#+id/editTextUserName"
android:layout_marginTop="20dp"
android:ems="10"
android:inputType="textPersonName"
android:hint="Address" />
<Button
android:id="#+id/buttonLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/address"
android:layout_centerHorizontal="true"
android:layout_marginTop="47dp"
android:text="Button" />
</RelativeLayout>
</ScrollView>
</RelativeLayout>
In manifest.xml add these line:
android:theme="#style/AppTheme"
android:windowSoftInputMode="stateHidden|adjustPan"
Declare AppTheme in style.xml as per your theme requirement. Then if you do not need keyboard comes up while page loads, you can add below line in activity:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Happy Coding :-)

Related

Best way to unfocus edittext when user interacts with another (non-texual) input element

I have an activity with some edittexts and some checkboxes, etc.
I have validators set on text entries that get executed when a text entry loses focus. But the problem is when the user clicks/touches a checkbox, edittext doesn't lose focus and therefore the validator is not run.
What is the best way for causing unfocus of text entries when the user touches another input field? I know I can e.g. set a handler on every checkbox to force unfocusing of text fields happen, but I think there is probably a more concise/general method for this purpose; Setting a handler on every checkbox seems too cumbersome and error prone.
thank u.
You can try this way(it only is an example).
your_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/sv_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="EditText 1" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="EditText 2" />
..............other views................
</LinearLayout>
</ScrollView>
Using android:focusableInTouchMode="true" in the LinearLayout to make the EditText is focused when touching on it( or when starting this activity there is not auto focus to any EditText also).
In your activity:
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
ScrollView svContent = findViewById(R.id.sv_content);
svContent.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
int action = motionEvent.getAction();
if(action == MotionEvent.ACTION_MOVE || action == MotionEvent.ACTION_UP) {
View focusView = getCurrentFocus();
if (focusView != null) {
// The code for unfocus here
return true;
}
}
return false;
}
});
}

Android : flowlayout inner button with close icon onclick event

I have a requirement to create a button with close icon like as below:
i have use button and i have fatch problem when i click on button remove button.
but my requirement is onclick close icon when remove form list.
so please help me which control use so my problem solution.
Use this code it will solved your problem
buttondelete.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_RIGHT = 2;
if(event.getAction() == MotionEvent.ACTION_UP) {
if(event.getRawX() >= (buttondelete.getRight() - buttondelete.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
// your action here
return true;
}
}
return false;
}
});
i would add to flow layout customLaout which contains of grey background and linear layout with 2 elements inside. TextView and ImageView.
Both has own ClickListeners
something like:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/darker_gray"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_gravity="center"
android:text="Example Text"
android:id="#+id/buttonTextView"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="#+id/buttonExitIcon"
android:src="#drawable/your_image_source"
/>
</LinearLayout>
and add Click listeners for both imageView and TextView
{
RelativeLayout mainView = (RelativeLayout)findViewById(R.id.item);
View child = getLayoutInflater().inflate(R.layout.child, null);
Button bt_close = (Button)child.findviewById(R.id.btnclose);
bt_put.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RelativeLayout pView = (RelativeLayout)v.getParent();
mainView.removeView(pView);
}
});
mainView.addView(child);
}
Create a child.xml using the RelativeLayout with childs (TextView for text and Button as Remove button)
Inflate the xml layout , add each views into your main_layout and
setonclicklistner to button.
when clicked on button , get the parent view from the clicked view and remove the view from main_layout.
this may help you.

How to disable scrolling in HorizontalScrollView?

What i want in pictures:
On the words: i want to disable scrolling with formatting text inside HorizontalScrollView.
Part of XML:
<ScrollView
android:id="#+id/review_scrollview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="horizontal"
android:fillViewport="true"
android:layout_marginTop="10dp">
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tt_review_content"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Some long text"
android:scrollHorizontally="true"/>
</HorizontalScrollView>
</ScrollView>
Method(doesn't works):
private void setTtAreaWrapContent(boolean value) {
ViewGroup.LayoutParams params = textField.getLayoutParams();
if(value) { // Wrap content
textField.setWidth(scrollView.getWidth());
} else { // Scroll
params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
}
textField.setLayoutParams(params);
}
There is a very simple way to do this.
Check if the user wants to scroll or not and then store it in a boolean variable, shouldScroll.
Now do this in onCreate,
HorziontalScrollView scrollView= (HorizontalScrollView)findViewById(R.id.scrollView);
if(!shouldScroll)
scrollView.setOnTouchListener(new OnTouch());
You also need to define a class OnTouch extending the OnTouchListener
private class OnTouch implements OnTouchListener
{
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
}
Now for the TextView formatting, just use android:singleLine="false" or use android:width="0dip"
I had absolutely the same need for code, so I initially proposed a ViewSwitcher with the same layouts, but one with HorizontalScrollView and one without it. And switch to the corresponding view depending on the setting.
However, I found an easier solution. After recreation of the Activity (when wrapping settings are changed by the user), use the code in the onCreate methode:
if (isWrapContent)
{
View mTV = findViewById(R.id.my_text_view);
HorizontalScrollView myHSV = (HorizontalScrollView) findViewById(R.id.my_hsv);
ViewGroup parent = (ViewGroup) myHSV.getParent();
ViewGroup.LayoutParams params = myHSV.getLayoutParams();
int index = parent.indexOfChild(myHSV);
myHSV.removeAllViews();
parent.removeView(myHSV);
parent.addView(mTV, index, params);
}
You need to use your id's and variables correspondingly.
It will remove the horizontal scrollview with the embedded textview and then reinsert the textview.
My answer provides direct and valid answer on how the asked issue could be resolved instead of freezing the horizontal scrollview or wondering about the point of the question, as it is done in the other comments and answers.

Disable soft keyboard on NumberPicker

I'm trying to deactivate the soft keyboard when using a NumberPicker to enter numerical values (for aesthetic reasons). This is my layout-xml-code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="30dp"
android:layout_marginTop="30dp" >
<NumberPicker
android:id="#+id/repetitionPicker"
android:layout_width="40dp"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="#string/repetitions_short_divider"
android:textAppearance="?android:attr/textAppearanceMedium" />
<NumberPicker
android:id="#+id/weightPicker"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="#string/pounds"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
<Button
android:id="#+id/saveButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="#string/save" />
</LinearLayout>
And finally this is the code where I try to block the keyboard in the onCreate()-method:
// hide keyboard
View.OnClickListener disableKeyBoardListener = new View.OnClickListener() {
public void onClick(View v) {
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
};
((EditText) weightPicker.getChildAt(1)).setInputType(InputType.TYPE_NULL);
((EditText) repetitionPicker.getChildAt(1)).setInputType(InputType.TYPE_NULL);
((EditText) weightPicker.getChildAt(1)).setOnClickListener(disableKeyBoardListener);
//((EditText) repetitionPicker.getChildAt(1)).setOnClickListener(disableKeyBoardListener);
//weightPicker.setOnClickListener(disableKeyBoardListener);
//repetitionPicker.setOnClickListener(disableKeyBoardListener);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Sadly, the soft keyboard still shows up when clicking on a NumberPicker. Any ideas?
Just found this and it works like a charm:
myNumberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
You can also set this in XML:
android:descendantFocusability="blocksDescendants"
Xml version of Andrew Webber's answer
android:descendantFocusability="blocksDescendants"
Example
<NumberPicker
android:id="#+id/your_numberpicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"/>
After reading through the com/android/internal/widget/NumberPicker.java source code i got to the following solution:
// Hide soft keyboard on NumberPickers by overwriting the OnFocusChangeListener
OnFocusChangeListener fcl = new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
// Do nothing to suppress keyboard
}
};
((EditText) numberPicker.getChildAt(1)).setOnFocusChangeListener(fcl);
// Suppress soft keyboard from the beginning
((EditText) numberPicker.getChildAt(1)).setInputType(InputType.TYPE_NULL);
Just enhanced the #MaxVogler 's ans (so if wannt vote this vote #MaxVogler too) and make it a robust hack. Also we dont need to call setOnFocusChangeListener and setInputType. Only setFocusable to false will do.
Below is a helper api to enable/disable the feature
public static void enableNumberPickerManualEditing(NumberPicker numPicker,
boolean enable) {
int childCount = numPicker.getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = numPicker.getChildAt(i);
if (childView instanceof EditText) {
EditText et = (EditText) childView;
et.setFocusable(enable);
return;
}
}
}
Here's another way to do it which enables the user still to edit a number if they want to - it just suppresses the soft keyboard initially. Use NumberPicker.setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS) to suppress the soft keyboard when the interface first shows as per answers above. Then get your dialog or activity to implement View.OnTouchListener, call setOnTouchListener(this) on your NumberPicker, and in your implementation of onTouch(View v,MotionEvent e) reset the numberpicker descendant focusability to its normal value, then return false.
Returning false means that the touch is still processed by the NumberPicker, which means that if the user taps the edit box the soft keyboard comes up. This happens to be exactly what I wanted faced with the same problem - having the soft keyboard come up with the dialog when it first shows is displeasing as it shifts the dialog up after it appears.
public class GetBufferDialog extends DialogFragment implements View.OnTouchListener {
after creating the Dialog in the onCreateDialog() method and finding the NumberPicker:
m_oldFocus = m_numberpicker.getDescendantFocusability();
m_numberpicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
m_numberpicker.setOnTouchListener(this);
and here's the OnTouch method:
public boolean onTouch(View v, MotionEvent event) {
m_numberpicker.setDescendantFocusability(m_oldFocus);
return false;
}
Working code
Programatically :
mp.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
XML:
android:descendantFocusability="blocksDescendants"
I don't know why it works, but setting OnClickListener which does nothing prevented keyboard from showing (Lollipop)
numberPicker.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
The simplest I found to work was :
numberPicker = (NumberPicker) myDialogView.findViewById(R.id.myViewId);
EditText numberPickerChild = (EditText) numberPicker.getChildAt(0);
numberPickerChild.setFocusable(false);
numberPickerChild.setInputType(InputType.TYPE_NULL);
If you only want to hide the software keyboard when loading the view with your number picker, but still want the users to be able to edit after the view loads, then you shouldn't block descendant focusability. Instead, just prevent the number picker from being the first focused item in your view.
See this answer for details.
Based on the above answer:
<!-- Dummy item to prevent Number Picker from receiving focus -->
<LinearLayout
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="0px"
android:layout_height="0px"/>
<!-- :nextFocusUp and :nextFocusLeft have been set to the id of this component
to prevent the dummy from receiving focus again -->
<NumberPicker
android:id="#+id/number_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusUp="#id/number_picker"
android:nextFocusLeft="#id/number_picker"/>
/**
* set focus to top level window
* disposes descendant focus
* disposes softInput
* #param context - activity context
* #param enable - state of focus
* */
public static void topLevelFocus(Context context, boolean enable){
if(Activity.class.isAssignableFrom(context.getClass())){
ViewGroup tlView = (ViewGroup) ((Activity) context).getWindow().getDecorView();
if(tlView!=null){
tlView.setFocusable(enable);
tlView.setFocusableInTouchMode(enable);
tlView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
tlView.requestFocus();
}
}
}
* calling this:
will not block descendant focusability (numberpicker will be editable)
will hide soft input on create
before (processing input) getValue() will allow to get proper walue
This extension is nice to not forget how to do it and have readable code. It is little bit hiding implementation details, but in this case I believe it's acceptable:
fun NumberPicker.disableTextEditing(disable: Boolean) {
descendantFocusability = if (disable) FOCUS_BLOCK_DESCENDANTS else FOCUS_BEFORE_DESCENDANTS
}

View over Canvas Visibility issue

I have this layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.components.game.GameView
android:id="#+id/game_id"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<RelativeLayout
android:id="#+id/ChatLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:visibility="invisible"
android:focusable="true"
android:focusableInTouchMode="true" >
<Button
android:id="#+id/ChatCancelButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="X" />
<Button
android:id="#+id/ChatOkButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="OK" />
<EditText
android:id="#+id/ChatEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#+id/ChatOkButton"
android:layout_toRightOf="#+id/ChatCancelButton"
android:maxLength="50"
android:singleLine="true" />
</RelativeLayout>
</RelativeLayout>
It's a RelativeLayout over a canvas. At start time it's invisible but when a user clicks a button the layout should become visible.
The problem is that it's not becoming visible. The layout is there but it's just not drawing it. If I press the position where the layout should appear it receives the event and opens the keyboard but it's not drawing the whole layout.
What is the problem?
If I set the RelativeLayout to visible at the beginning it works fine. it shows the layout and if I toggle between invisible and visible it works fine.
I made a workaround that almost always works.
I start the layout visible and than do that in the oncreate:
chatLayout.postDelayed(new Runnable() {
#Override
public void run() {
chatLayout.setVisibility(View.INVISIBLE);
}
}, 50);
But I don't like it and want to understand what's the problem.
The code:
It starts from a canvas button which send a message to a handler:
public void showInputLayout() {
Message.obtain(gameHandler, SHOW_INPUT_LAYOUT).sendToTarget();
}
In the handler:
case SHOW_INPUT_LAYOUT:
gameActivity.setChatVisibility(true);
break;
setChatVisibility:
public void setChatVisibility(boolean isVisible) {
int visible = isVisible ? View.VISIBLE : View.INVISIBLE;
chatLayout.setVisibility(visible);
if(isVisible){
chatEditText.setFocusable(true);
chatEditText.requestFocus();
}
}
Add a click listener to RelativeLayout and switch the visibility between GONE and VISIBLE. Try something like this:
int visibility = View.VISIBLE;
RelativeLayout layout = (RelativeLayout)findViewById(R.id.ChatLayout);
layout.setVisibility(visibility);
layout.setOnClickListener(new View.OnClickListener{
public void onClick(View v)
{
if(visibility == View.VISIBLE)
visibility = View.GONE;
else
visibility = View.VISIBLE;
v.setVisibility(visibility);
}
})
I ran into a similar issue recently, and for my case the problem was actually in the onDraw() method of the view underneath (should be com.components.game.GameView in your case). See if you can add calls to Canvas' getSaveCount(), save() and restoreToCount() in your drawing code, similar to this:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int saveCount = canvas.getSaveCount();
canvas.save();
// custom drawing code here ...
// use Region.Op.INTERSECT for adding clipping regions
canvas.restoreToCount(saveCount);
}
I believe what happened was that sometimes the framework set the clipping regions for the elements on top of our Canvas-drawing widget before our onDraw() method is called so we need to make sure that those regions are preserved.
Hope this helps.

Categories

Resources