2011-07-23 14 views
4

私はFastSelectEditTextを作るしようとしている、よう:iphoneのようなEditText用の拡大鏡:ビューの外に描画することは可能ですか?

  1. テキストが長いクリックで選択し、指をスライドすることができます。
  2. スライドして選択するときに、(iPhoneのような)拡大鏡を表示すると、ユーザーは指の下のテキストを見ることができます。

残念ながら私のデザインに問題があります.MagGlassは自分のFastSelectEditText内にのみ表示されます。ユーザーがトップラインでテキストを選択しているときは、マガガラスを見ることができません。
私はこの問題を回避する必要があります:指がFastSelectEditTextの一番上に届いたら、マガガラスを指より低く見せてください。

私はMag Glassの別のビューを使用しても問題はありません。しかしコードをシンプルにするために、MagSightをFastSelectEditTextの中に入れておく方がよいと思います。

ビューの境界外に何かを描画する方法はありますか?
それとも私が?マググラスを実装するために(代わりにカスタマイズされたのEditText内部のいくつかのコードの)別のビューを作成する(そしておそらく、フレームレイアウトの内側にこれらのビューを置く?)する必要があり

The mag glass is showing upper than the finger touched
The mag glass is showing lower than the finger touched

public class FastSelectEditText extends EditText implements OnLongClickListener { 

/** 
* @param context 
*/ 
public FastSelectEditText(Context context) { 
    super(context); 
    init(); 
} 

/** 
* @param context 
* @param attrs 
*/ 
public FastSelectEditText(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    init(); 
} 

/** 
* @param context 
* @param attrs 
* @param defStyle 
*/ 
public FastSelectEditText(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    init(); 
} 

private MagGlass mMagGlass; 
private float mScale; 
private void init(){ 
    DisplayMetrics metrics = getResources().getDisplayMetrics(); 
    mScale = metrics.density; 
    setGravity(Gravity.TOP); 
    setOnLongClickListener(this); 
    mMagGlass = new MagGlass(); 
} 

private int getOffset(int x, int y){ 
    Layout layout = getLayout(); 
    int row = layout.getLineForVertical(getScrollY()+y-getPaddingTop()); 
    return layout.getOffsetForHorizontal(row, x-getPaddingLeft()); 
} 

/** 
* the position/index when touch down. 
*/ 
private int mDownOffset = 0; 
private int mOldSelStart, mOldSelEnd; 
/** 
* Did the user moved his finger after down event? 
*/ 
private boolean mMoved = false; 
@Override 
public boolean dispatchTouchEvent(MotionEvent event) { 
    int x = (int) event.getX(); 
    int y = (int) event.getY(); 
    mMagGlass.setObjectCenter(x, y); 
    boolean result; 
    switch (event.getAction()){ 
    case MotionEvent.ACTION_DOWN: 
     mOldSelStart = getSelectionStart(); 
     mOldSelEnd = getSelectionEnd(); 
     if (mOldSelStart != mOldSelEnd){ 
      startSlideAndSelect(); 
     } 
     mDownOffset = getOffset(x, y); 
     return super.dispatchTouchEvent(event); 
    case MotionEvent.ACTION_MOVE: 
     result = super.dispatchTouchEvent(event); 
     int offset = getOffset(x, y); 
     if (!mMoved && mDownOffset != offset){ 
      mMoved = true; 
     } 
     if (mSlideAndSelect){    
      if (mMoved){ 
       setSelection(mDownOffset, offset); 
      } 
      return true; 
     } 
     return result; 
    case MotionEvent.ACTION_UP: 
     boolean moved = mMoved; 
     // reset mMoved 
     mMoved = false; 

     boolean longClicked = mLongClicked; 
     mLongClicked = false; 

     if (mSlideAndSelect && moved){ 
      event.setAction(MotionEvent.ACTION_CANCEL); 
     } 
     result = super.dispatchTouchEvent(event); 
     if (mSlideAndSelect){ 
      mSlideAndSelect = false; 
      int upOffset = getOffset(x, y); 
      if (!moved && mDownOffset == upOffset && longClicked){ 
       setSelection(mOldSelStart, mOldSelEnd); 
       showContextMenu(); 
      }else{ 
       setSelection(mDownOffset, upOffset); 
      } 
      return true; 
     } 
     return result; 
    case MotionEvent.ACTION_CANCEL: 
     mSlideAndSelect = false; 
     // reset mMoved 
     mMoved = false; 
     mLongClicked = false; 
     return super.dispatchTouchEvent(event); 
    default: 
     return super.dispatchTouchEvent(event); 
    } 
} 

protected void startSlideAndSelect() { 
    mSlideAndSelect = true; 
    ViewParent parent = getParent(); 
    if (parent != null){ 
     parent.requestDisallowInterceptTouchEvent(true); 
    } 
} 

private boolean mSlideAndSelect = false; 
private boolean mLongClicked = false; 

private Vibrator mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE); 
@Override 
public boolean onLongClick(View v) { 
    if (!mMoved){ 
     startSlideAndSelect(); 
     mLongClicked = true; 
     mVibrator.vibrate(30); 
    } 
    return true; 
} 

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 
    if (mSlideAndSelect){ 
     mMagGlass.draw(canvas); 
    } 
} 

/** 
* Need a drawable.mag_glass to work. 
* 
* @author lifurong 
* 
*/ 
class MagGlass{ 
    private int mWidth, mHeight; 
    private Bitmap mMagGlassBitmap; 
    private int mX, mY; 
    private final static int INSET = 10; 

    public MagGlass(){ 
     mMagGlassBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mag_glass); 
     mWidth = mMagGlassBitmap.getWidth(); 
     mHeight = mMagGlassBitmap.getHeight(); 
    } 
    public void setObjectCenter(int x, int y){ 
     mX = x; 
     mY = y; 
    } 

    public void draw(Canvas canvas) { 
     final float left = mX-mWidth/2.0f; 
     final float top = mY-mHeight/2.0f; 
     final float right = mX+mWidth/2.0f; 
     final float bottom = mY+mHeight/2.0f; 
     float vTrans = 80*mScale; 
     int vTransSign; 
     int[] location = new int[2]; 
     getLocationInWindow(location); 
     int topEdge = location[1]-getPaddingTop()>0? 0:-location[1]+getPaddingTop(); 
     if (top-vTrans > topEdge){ 
      vTransSign = -1; 
     }else{ 
      vTransSign = 1; 
     } 
     canvas.translate(0, vTrans*vTransSign); 
     canvas.clipRect(left, top, right, bottom); 
     canvas.drawBitmap(mMagGlassBitmap, left, top, null); 
     canvas.clipRect(left+INSET, top+INSET, right-INSET, bottom-INSET); 
     FastSelectEditText.super.onDraw(canvas); 
    } 
} 

}

答えて

2

ビューの境界外で描画す​​るには、ビューの親のclipChildrenに設定する必要があります0。

デフォルトではViewGroupはがtrueに設定されています。その結果、子は境界にクリップされたキャンバスに描画されます。

+0

ありがとうございました!はい、clipChildrenがポイントです。しかし残念なことに、私がそれを真実にしようとすると、それは他の子供たちの描く行動にも影響します(彼らはすべて野生になります)。 –

関連する問題