View.setX препятствует работе AdjustPan
Я программно устанавливаю значение х edittext
, Однако при этом функция настройки панорамирования не работает. Любые идеи о том, как сделать эту работу. activity
не в полноэкранном режиме, и это происходит только в APIs > 23
,
Ex.
Edittext editext = findViewById(R.id.edittext);
edittext.setX(200);
// Нажав на edittext
теперь покрывается мягкой клавиатурой, если она достаточно низко на экране
Примечание: это также происходит с setY()
Вот пример для воспроизведения ошибки:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context context = this;
setContentView(R.layout.activity_main);
//Get edittext from layout file and set X and Y to the bottom
//left of screen
EditText edittext = findViewById(R.id.editText);
edittext.setX(0);
//Getting device frame to make sure its below keyboard, Not
//necessary can just guess any value
edittext.setY(getDeviceFrame(context).getHeight() / 1.2f);
}
С макетом:
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
И манифест:
<activity android:name=".MainActivity"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
В результате получается макет: Edittext после программных setX и setY
И после нажатия на editext мы получаем: Скрытый editext
То, что вы видите, скрыто клавиатурой.
ОБНОВЛЕНИЕ: я попытался использовать различные варианты для перемещения EditText безрезультатно.
Ex.
edittext.animate().x(200);
ОБНОВЛЕНИЕ 2: мне еще предстоит решить эту проблему. Я подошел ближе, поскольку провел некоторый тест, и кажется, что использование параметров макета для управления позиционированием вида работает до некоторой степени.
Ex.
ConstraintLayout.LayoutParams layoutParams =
(ConstraintLayout.LayoutParams) view.getLayoutParams();
layoutParams.leftMargin = 200; //Your X Coordinate
layoutParams.topMargin = 200; //Your Y Coordinate
view.setLayoutParams(layoutParams);
В некоторой степени, я имею в виду, что я испортил функциональность этих методов в тестовой библиотеке, и, похоже, работает с вышеупомянутым из onCreate(). Тем не менее, в моем приложении, я делаю вызов в обратном вызове. SetX работает нормально, без необходимости устанавливать его в ветке 'post' или в ветке 'runOnMainUI'. Поэтому я не уверен, почему это не работает.
1 ответ
Итак, я разобрался, как решить проблему. Используя ответ из моего "Обновления 2" выше, я смог получить решение с небольшой настройкой.
Этот код:
ConstraintLayout.LayoutParams layoutParams =
(ConstraintLayout.LayoutParams) view.getLayoutParams();
layoutParams.leftMargin = 200; //Your X Coordinate
layoutParams.topMargin = 200; //Your Y Coordinate
view.setLayoutParams(layoutParams);
(Вы можете использовать любой макет, который вы используете вместо ограничения)
Является альтернативой setX() и setY() и позволяет настроить AdjustPan для работы. Тем не менее, получение вида x или y с помощью:
view.getX();
view.getY();
Не вернет визуальное позиционирование вида. Вы должны получить позицию представления, получая параметры макета, связанные с представлением, и получая его поля.
Теперь я пришел к выводу, что ключом к макету ограничения является то, что вы ДОЛЖНЫ иметь ограничение, определенное в xml или с помощью кода.
Ex.
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
Имея это, поля могут иметь ссылку на то, с чего они были расширены, без этого, позиционирование вида без движения.
Заменить setX
а также setY
с leftMargin
а также topMargin
для всплывающего позиционирования, и он будет работать, как задумано, на API выше 23.
Я не могу объяснить, почему, но проблема не существовала в API 23.
Как предлагается, вот образец кода, используемого для перемещения макета всплывающего окна путем перетаскивания кнопки и сохранения работы настройки панорамирования.
final View myNote = getActivity().getLayoutInflater().inflate(R.layout.viewer_annotation_layout, null);
final RelativeLayout.LayoutParams noteLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
myNote.setLayoutParams(noteLayoutParams);
mainScreenLayout.addView(myNote, noteLayoutParams);
btnmove.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
//addednotedX = myNote.getX() - event.getRawX();
//addednotedY = myNote.getY() - event.getRawY();
addednotedX = noteLayoutParams.leftMargin - event.getRawX();
addednotedY = noteLayoutParams.topMargin - event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int newposx = event.getRawX() + addednotedX;
int newposy = event.getRawY() + addednotedY;
/* this is move the Note layout but prevent adjsutpan working */
//myNote.setX(newposx);
//myNote.setY(newposy);
/* this is move the Note layout and keep adjsutpan working */
noteLayoutParams.leftMargin = newposx;
noteLayoutParams.topMargin = newposy;
myNote.setLayoutParams(noteLayoutParams);
break;
default:
return false;
}
return false;
}
});