mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-30 23:27:22 +00:00
WIP: android cursor handle
This commit is contained in:
parent
98daa71010
commit
291a0bdc66
3 changed files with 94 additions and 9 deletions
|
@ -71,7 +71,7 @@ impl i_slint_core::window::WindowAdapterInternal for AndroidWindowAdapter {
|
|||
match request {
|
||||
i_slint_core::window::InputMethodRequest::Enable(props) => {
|
||||
self.java_helper
|
||||
.set_imm_data(&props)
|
||||
.set_imm_data(&props, self.window.scale_factor())
|
||||
.unwrap_or_else(|e| print_jni_error(&self.app, e));
|
||||
self.java_helper
|
||||
.show_or_hide_soft_input(true)
|
||||
|
@ -79,7 +79,7 @@ impl i_slint_core::window::WindowAdapterInternal for AndroidWindowAdapter {
|
|||
}
|
||||
i_slint_core::window::InputMethodRequest::Update(props) => {
|
||||
self.java_helper
|
||||
.set_imm_data(&props)
|
||||
.set_imm_data(&props, self.window.scale_factor())
|
||||
.unwrap_or_else(|e| print_jni_error(&self.app, e));
|
||||
}
|
||||
i_slint_core::window::InputMethodRequest::Disable => {
|
||||
|
|
|
@ -1,20 +1,92 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Editable;
|
||||
import android.text.Selection;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.app.Activity;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupWindow;
|
||||
import android.view.inputmethod.BaseInputConnection;
|
||||
|
||||
class InputHandle extends ImageView {
|
||||
private PopupWindow mPopupWindow;
|
||||
private float mPressedX;
|
||||
private float mPressedY;
|
||||
private SlintInputView mRootView;
|
||||
|
||||
public InputHandle(SlintInputView rootView, int attr) {
|
||||
super(rootView.getContext());
|
||||
mRootView = rootView;
|
||||
Context ctx = rootView.getContext();
|
||||
// this.mInputView = mInputView;
|
||||
|
||||
mPopupWindow = new PopupWindow(ctx, null, android.R.attr.textSelectHandleWindowStyle);
|
||||
mPopupWindow.setSplitTouchEnabled(true);
|
||||
mPopupWindow.setClippingEnabled(false);
|
||||
int[] attrs = { attr };
|
||||
Drawable drawable = ctx.getTheme().obtainStyledAttributes(attrs).getDrawable(0);
|
||||
mPopupWindow.setWidth(drawable.getIntrinsicWidth());
|
||||
mPopupWindow.setHeight(drawable.getIntrinsicHeight());
|
||||
this.setImageDrawable(drawable);
|
||||
|
||||
// mPopupWindow.setBackgroundDrawable(null);
|
||||
// mPopupWindow.setAnimationStyle(0);
|
||||
// mPopupWindow.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
|
||||
// mPopupWindow.setEnterTransition(null);
|
||||
// mPopupWindow.setExitTransition(null);
|
||||
|
||||
mPopupWindow.setContentView(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
switch (ev.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
mPressedX = ev.getRawX();
|
||||
mPressedY = ev.getRawY();
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
// setSelectionAt
|
||||
// (Math.round(ev.getRawX() - mPressedX), Math.round(ev.getRawY() - mPressedY));
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setPosition(int x, int y) {
|
||||
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
|
||||
y += mPopupWindow.getHeight();
|
||||
x -= mPopupWindow.getWidth() / 2;
|
||||
mPopupWindow.showAtLocation(mRootView, 0, x, y);
|
||||
mPopupWindow.update(x, y, -1, -1);
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
mPopupWindow.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
class SlintInputView extends View {
|
||||
private String mText = "";
|
||||
private int mCursorPosition = 0;
|
||||
|
@ -34,6 +106,7 @@ class SlintInputView extends View {
|
|||
@Override
|
||||
public SpannableStringBuilder replace(int start, int end, CharSequence tb, int tbstart, int tbend) {
|
||||
super.replace(start, end, tb, tbstart, tbend);
|
||||
mHandle.hide();
|
||||
if (mInBatch == 0) {
|
||||
update();
|
||||
} else {
|
||||
|
@ -127,6 +200,15 @@ class SlintInputView extends View {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private InputHandle mHandle;
|
||||
|
||||
public void setCursorPos(int rect_x, int rect_y, int rect_w, int rect_h) {
|
||||
if (mHandle == null) {
|
||||
mHandle = new InputHandle(this, android.R.attr.textSelectHandle);
|
||||
}
|
||||
mHandle.setPosition(rect_x + rect_w / 2, rect_y + rect_h + 2 * rect_w);
|
||||
}
|
||||
}
|
||||
|
||||
public class SlintAndroidJavaHelper {
|
||||
|
@ -178,12 +260,10 @@ public class SlintAndroidJavaHelper {
|
|||
mActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(rect_w, rect_h);
|
||||
layoutParams.setMargins(rect_x, rect_y, 0, 0);
|
||||
mInputView.setLayoutParams(layoutParams);
|
||||
int selStart = Math.min(cursor_position, anchor_position);
|
||||
int selEnd = Math.max(cursor_position, anchor_position);
|
||||
mInputView.setText(text, selStart, selEnd, preedit_start, preedit_end, input_type);
|
||||
mInputView.setCursorPos(rect_x, rect_y, rect_w, rect_h);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -103,6 +103,7 @@ impl JavaHelper {
|
|||
pub fn set_imm_data(
|
||||
&self,
|
||||
data: &i_slint_core::window::InputMethodProperties,
|
||||
scale_factor: f32
|
||||
) -> Result<(), jni::errors::Error> {
|
||||
self.with_jni_env(|env, helper| {
|
||||
let mut text = data.text.to_string();
|
||||
|
@ -138,6 +139,10 @@ impl JavaHelper {
|
|||
}
|
||||
_ => 0 as jint,
|
||||
};
|
||||
|
||||
let cur_origin = data.cursor_rect_origin.to_physical(scale_factor);
|
||||
let cur_size = data.cursor_rect_size.to_physical(scale_factor);
|
||||
|
||||
env.call_method(
|
||||
helper,
|
||||
"set_imm_data",
|
||||
|
@ -148,10 +153,10 @@ impl JavaHelper {
|
|||
JValue::from(to_utf16(anchor_position) as jint),
|
||||
JValue::from(to_utf16(data.preedit_offset) as jint),
|
||||
JValue::from(to_utf16(data.preedit_offset + data.preedit_text.len()) as jint),
|
||||
JValue::from(data.cursor_rect_origin.x as jint),
|
||||
JValue::from(data.cursor_rect_origin.y as jint),
|
||||
JValue::from(data.cursor_rect_size.width as jint),
|
||||
JValue::from(data.cursor_rect_size.height as jint),
|
||||
JValue::from(cur_origin.x as jint),
|
||||
JValue::from(cur_origin.y as jint),
|
||||
JValue::from(cur_size.width as jint),
|
||||
JValue::from(cur_size.height as jint),
|
||||
JValue::from(input_type),
|
||||
],
|
||||
)?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue