Amir Hossein Mafi Amir Hossein Mafi - 21 days ago 6
Android Question

bringToFront doesn't work correctly in android

I created a custom view and put about 14

EditText
on it. I wanted to change the position of one of
EditText
, so at first I used
editText.bringToFront();
then I changed the position of this button with the Index of this
EditText
getChildAt(childIndex).setY(y);
. I was surprised when I saw that all the
EditTexts
that their index is upper than this button are moving. I don't know why
bringToFront
method change the index of other
EditTexts
.

Simplified source code with
Button
(Not
EditText
). This works correctly without
bringToFront()
. But I want To use
EditText
:

public class CustomView extends ViewGroup{

private int height;
private int childCount;
int chosenIndex;

public CustomView(Context context) {
super(context);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
childCount = getChildCount();
height = 200;

for (int childIndex = 0; childIndex < childCount; childIndex++) {
Button child = (Button) getChildAt(childIndex);
child.layout(l, childIndex * height, r, (childIndex + 1) * height);
child.setText("" + childIndex);
}
}

public boolean onInterceptTouchEvent(MotionEvent ev) {
super.onInterceptTouchEvent(ev);

float y = ev.getY();

switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
for (int i = 0; i < childCount; i++) {
if (getChildAt(i).getY() < y && getChildAt(i).getY() + getChildAt(i).getHeight() > y) {
chosenIndex = i;
}
}
break;

case MotionEvent.ACTION_MOVE:
// No bringToFront()
getChildAt(chosenIndex).setY(y);
break;

case MotionEvent.ACTION_UP:
getChildAt(chosenIndex).setY(y);
break;
}

return false;
}

}


Source Code with
EditText
(The Problem is here, this doesn't work with
bringToFront()
or without it)

public class CustomView extends ViewGroup{

private int height;
private int childCount;
int chosenIndex;

public CustomView(Context context) {
super(context);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
childCount = getChildCount();
height = 200;

for (int childIndex = 0; childIndex < childCount; childIndex++) {
EditText child = (EditText) getChildAt(childIndex);
child.layout(l, childIndex * height, r, (childIndex + 1) * height);
int color = Color.rgb(childIndex * 40, 0, 0);
child.setBackgroundColor(color);
child.setText("" + childIndex);
}
}

public boolean onInterceptTouchEvent(MotionEvent ev) {
super.onInterceptTouchEvent(ev);

float y = ev.getY();

switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
for (int i = 0; i < childCount; i++) {
if (getChildAt(i).getY() < y && getChildAt(i).getY() + getChildAt(i).getHeight() > y) {
chosenIndex = i;
}
}
break;

case MotionEvent.ACTION_MOVE:
getChildAt(chosenIndex).bringToFront(); // Here is the problem with BringToFront
getChildAt(chosenIndex).setY(y);
break;

case MotionEvent.ACTION_UP:
getChildAt(chosenIndex).setY(y);
break;
}

return false;
}

}

Answer

The issue is probably due to the elevation parameter (it's present on >= Lollipop versions).

Try this:

  1. Set ViewCompat.setElevation(btn, 0); on all of your Buttons
  2. Not only call btn.bringToFront() but also ViewCompat.setElevation(btn, someLargerThanZeroValue) when you want to move your Button above others.