Ampliar vidrio para EditText como en iphone: ¿es posible dibujar fuera de una vista?
Estoy intentando hacer un FastSelectEditText, de modo que:
- El texto puede seleccionarse con un clic largo y deslizar el dedo.
- Al deslizar y seleccionar, mostrar un cristal de aumento (como iphone), para que el usuario puede ver el texto bajo su dedo.
Lamentablemente hay un problema con mi diseño: El MagGlass muestra sólo dentro de mi FastSelectEditText. Cuando el usuario está seleccionando el texto en las líneas superiores, no puede ver el vidrio mag.
Así que tengo que usar este trabajo alrededor: mostrar el vidrio mag inferior al dedo, cuando llega a la parte superior de la FastSelectEditText.
- Agregar vista al grupo de vistas xml existente en el código
- Android Cómo obtener una vista previa de una imagen, utilizando su ruta de acceso desde SDcard, desde mi aplicación
- No se puede establecer ExpandableListView Child DividerHeight
- Diferencia entre vista y subvista - Android
- ImageView - Zoom en estiramiento o despliegue hacia abajo
Entiendo que si utilizo otra vista para Mag Glass, eso no será un problema. Pero para mantener el código simple, creo que es mejor mantener el vidrio Mag dentro de FastSelectEditText.
¿Hay alguna manera de dibujar algo fuera del límite de una vista?
¿O debería escribir otra vista (en lugar de algún código dentro del Custom EditText) para implementar un Mag Glass? (Y probablemente poner estas vistas dentro de un marco de diseño?)
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); } }
}
- Android WebView ZoomManager.onSizeChanged NullPointerException
- Ver onDraw (Canvas c) versus dibujar (Canvas c) en android?
- Surface - dequeueBuffer failed (Error desconocido 2147483646)
- Eliminar márgenes en webView
- ¿Cuál es la forma correcta de comunicarse desde una Vista personalizada a la Actividad en la que reside?
- Android ViewAnimator / ViewFlipper / ViewSwitcher y valor de hardcoded para setDisplayedChild
- Ver los valores devueltos getHeight () y getWidth () demasiado grandes
- Cómo deshabilitar el desplazamiento horizontal en la vista web de Android
Para dibujar fuera del límite de una vista, debe establecer el clipChildren
del padre de la clipChildren
en false
.
De forma predeterminada, un grupo de ViewGroup
tiene el clipChildren
establecido en true
, lo que provocó que los niños dibujen en un lienzo recortado a sus límites.
- ¿Alguien ha intentado usar javax.persistence en Android?
- Iniciar nueva actividad desde la notificación en android