我基于http://alinberce.wordpress.com/2012/02/20/android-edittext-with-custom-font-and-clear-button/松散地创建了一个自定义EditText。我的应用程序的主要xml是一个RelativeLayout,它包含一堆控制按钮和一个扩展View的自定义drawview类。当点击一个按钮时,我能够以编程方式将EditText添加到主xml中,并且它在那里工作:我可以通过拖动它的角来调整它的大小,然后按下>将其拖动到屏幕上。 100毫秒。
因为可以通过控制按钮移动EditText,我觉得EditText的正确位置在drawview中。所以我将drawview更改为ViewGroup,并添加了我希望将EditText放在那里的适当代码。我没有对自定义EditText如何操作进行任何更改(只是足以让它出现在Viewgroup而不是View中),但现在它不像以前那样工作。它显示为正方形而不是矩形,并且不会通过触摸移动或调整大小。
我一直在努力使用各种LayoutParams和MarginLayoutParams,以及editText.setMinimumHeight和.setMinimumWidth,但更改这些似乎没有任何区别。抽象地说,我知道我需要覆盖ViewGroup中的onMeasure并测量子节点。抽象地说,我知道我需要覆盖onLayout并执行editText.layout,看起来我应该创建一个Rect来定义它的边界,但是因为它应该在输入文本时原生自动化,并在拖动角落时调整大小,我不会知道Rect是否正确。我应该使用哪些具体方法?我没有从api文档中推断出来的经验。例子。有人能指出我正确的方向吗?
编辑:
绘制视图太长而无法发布,onMeasure和onLayout上的覆盖是我正在寻求帮助的。
将editText添加到drawview:
private void addEditText() {
final MovableEditText et = new MovableEditText(app);
// I know this is terrifically messy
et.setMinimumWidth(50);
et.setMinimumHeight(30);
et.setTextSize(app.getTextSize());
et.setTextColor(app.getLineColor());
et.setBackgroundColor(Color.parseColor("#77CCCCCC")); // some kind of light transparent gray
et.setText(app.getText());
et.setTag("TEXTENTRY");
et.setTextCompletedListener(new TextCompletedListener() {
@Override
public void onTextCompleted() {
removeEditText();
drawView.invalidate();
}
});
app.editText = et;
// place the new editText sorta top center of the screen
// Rect clipBounds = drawView.getClipBounds();
DrawView dv = (DrawView) findViewById(R.id.drawview);
ViewGroup.MarginLayoutParams etParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
dv.addView(et, etParams);
et.requestFocus();
dv.invalidate();
InputMethodManager imm = (InputMethodManager) app.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.showSoftInput(et, 0);
}
}
edittext本身:
public class MovableEditText extends EditText {
// 2 drawables, a close (cancel) and a resize handle
private Drawable closeImg = getResources().getDrawable(R.drawable.text_ok);
private Drawable resizeImg = getResources().getDrawable(R.drawable.text_resize);
private long timeFingerDown;
private InputMethodManager imm;
private App app;
private boolean resizing;
private TextCompletedListener textListener;
public MovableEditText(Context context) {
super(context);
app = (App) context.getApplicationContext();
imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
init();
}
public MovableEditText(Context context, AttributeSet attrs) {
super(context, attrs);
app = (App) context.getApplicationContext();
imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
init();
}
public MovableEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
app = (App) context.getApplicationContext();
imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
init();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
public void setTextCompletedListener(TextCompletedListener l) {
textListener = l;
}
private void init() {
// Set bounds of the Clear button so it will look ok
closeImg.setBounds(0, 0, closeImg.getIntrinsicWidth(), closeImg.getIntrinsicHeight());
resizeImg.setBounds(0, 0, resizeImg.getIntrinsicWidth(), resizeImg.getIntrinsicHeight());
// There may be initial text in the field, so we may need to display the button
showOkButton();
this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
MovableEditText et = MovableEditText.this;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
timeFingerDown = event.getEventTime();
return true;
case MotionEvent.ACTION_UP:
//if the Close image is displayed and the user remove his finger from the button, clear it. Otherwise do nothing
// Log.i("napkinapp", "event x,y = "+event.getX()+", "+event.getY());
if (resizing) {
resizing = false;
}
// clicking on the checkbox
if (event.getY() < et.getPaddingTop() + closeImg.getIntrinsicHeight()) {
et.okButtonClick();
return false;
}
// otherwise, show the keyboard
if (imm != null) {
imm.showSoftInput(MovableEditText.this, 0);
}
return false;
case MotionEvent.ACTION_MOVE:
if (event.getX() > et.getWidth() - et.getPaddingRight() - resizeImg.getIntrinsicWidth()) {
resizeBox(et, event);
// we touched the arrow, so we are resizing the box (i.e. increasing font size)
resizing = true;
return true;
}
if (event.getEventTime() - timeFingerDown > 200 && !resizing) {
// we are moving the box
moveBox(et, event);
}
return true;
}
return false;
}
});
//if text changes, take care of the button
this.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//
MovableEditText.this.showOkButton();
}
@Override
public void afterTextChanged(Editable arg0) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
});
}
private void moveBox(MovableEditText et, MotionEvent event) {
ViewGroup.MarginLayoutParams etParams = (ViewGroup.MarginLayoutParams) this.getLayoutParams();
etParams.leftMargin += (int) (event.getX() - (et.getWidth()/2));
etParams.topMargin += (int) (event.getY() - this.getHeight()) ;
et.setLayoutParams(etParams);
}
private void resizeBox(MovableEditText et, MotionEvent event) {
et.setWidth((int) event.getX());
et.setHeight((int) event.getY());
resizeText(et);
}
private void resizeText(MovableEditText et) {
int height = (int) ((et.getHeight() - closeImg.getIntrinsicHeight())*.25);
et.setTextSize(height);
}
void showOkButton() {
if (this.getText().toString().equals("")) {
// remove the clear button
this.setCompoundDrawables(this.getCompoundDrawables()[0],null, resizeImg, this.getCompoundDrawables()[3] );
} else {
//add clear button
this.setCompoundDrawables(this.getCompoundDrawables()[0], closeImg, resizeImg, this.getCompoundDrawables()[3]);
}
}
void okButtonClick() {
// get the text, get the size, get the position, create a Stroke from it
if (this.getText().toString().length()>0) {
app.setText(this.getText().toString());
app.setTextSize(this.getPaint().getTextSize()*.5f);
ViewGroup.MarginLayoutParams etParams = (ViewGroup.MarginLayoutParams) this.getLayoutParams();
int left = this.getLeft() + etParams.leftMargin;
int bottom = this.getBottom() + etParams.topMargin + this.getHeight() - this.getPaddingBottom() ;
app.strokeInProgress = new TextStrokeBuilder(app, left, bottom);
}
// make the keyboard go away
imm.hideSoftInputFromWindow(this.getWindowToken(), 0);
// tell app to delete the EditText
textListener.onTextCompleted();
}
}
答案 0 :(得分:1)
所以我发现(或多或少)一个解决方案。我们摆脱了MoveableEditText的MarginLayoutParameters,它们非常烦人,而是为leftMargin和topMargin提供了字段,我们用100和100初始化了它。
将编辑文本添加的代码更改为:
private void addEditText() {
MovableEditText et = new MovableEditText(app);
et.setMinimumWidth(60);
et.setTextSize(app.getTextSize());
et.setTextColor(app.getLineColor());
et.setBackgroundColor(Color.parseColor("#77CCCCCC")); // some kind of light transparent gray
et.setText(app.getText());
et.setTag("TEXTENTRY");
et.setTextCompletedListener(new TextCompletedListener() {
@Override
public void onTextCompleted() {
removeEditText();
drawView.invalidate();
}
});
app.editText = et;
DrawView dv = (DrawView) findViewById(R.id.drawview);
dv.addView(et);
et.requestFocus();
InputMethodManager imm = (InputMethodManager) app.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.showSoftInput(et, 0);
}
}
将MoveableEditText中框移动的代码更改为:
private void moveBox(MovableEditText et, MotionEvent event) {
leftMargin += (int) (event.getX() - (et.getWidth()/2));
topMargin += (int) (event.getY() - this.getHeight());
requestLayout();
}
onLayout和onMeasure在此之后变得非常简单。
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < getChildCount(); i++) {
final MovableEditText child = (MovableEditText) getChildAt(i);
int left = l + child.leftMargin;
int top = t + child.topMargin;
child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).measure(width, height);
}
}