Dibujar contenido de TextView actual en Bitmap
Tengo un TextView en ScrollView:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/parentLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ScrollView android:id="@+id/textAreaScroller" android:layout_width="400px" android:layout_height="200px" android:layout_x="0px" android:layout_y="25px" android:fadeScrollbars="false" android:scrollbarSize="3px" android:scrollbarStyle="insideOverlay" > <TextView android:id="@+id/scrapbook" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="" /> </ScrollView> <Button android:id="@+id/upBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Up" /> <Button android:id="@+id/downBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Down" /> <ImageView android:id="@+id/imageView" android:layout_width="400px" android:layout_height="200px" /> </LinearLayout>
TextView tiene un montón de texto por eso es desplazable. Necesito dibujar el contenido visible actual en TextView a Bitmap. Para propósitos de prueba, muestro este mapa de bits en ImageView. Tengo el siguiente código:
- Cómo almacenar texto largo en Android?
- Cómo establecer el ancho de la ventana de texto wrap_content pero limitar a 1/3 del ancho de los padres
- Cambiar el color de fondo de un TextView cuando se hace clic
- Cómo agregar texto a editext
- Android / Java: ¿Determinar si el color del texto se mezclará con el fondo?
public class TextviewToImageActivity extends Activity { private TextView textView; private ScrollView textAreaScroller; private ImageView imageView; private Handler mHandler; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mHandler = new Handler(); imageView = (ImageView) findViewById(R.id.imageView); textAreaScroller = (ScrollView) findViewById(R.id.textAreaScroller); textView = (TextView) findViewById(R.id.scrapbook); textView.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { imageView.setImageBitmap(loadBitmapFromView(textAreaScroller)); return false; } }); Button upBtn = (Button) findViewById(R.id.upBtn); Button downBtn = (Button) findViewById(R.id.downBtn); upBtn.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { scheduleScroller(upScroller); imageView.setImageBitmap(loadBitmapFromView(textView)); } else if (event.getAction() == MotionEvent.ACTION_UP) { mHandler.removeMessages(1); } return true; } }); downBtn.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { scheduleScroller(downScroller); imageView.setImageBitmap(loadBitmapFromView(textView)); } else if (event.getAction() == MotionEvent.ACTION_UP) { mHandler.removeMessages(1); } return true; } }); loadDoc(); } private Runnable downScroller = new Runnable() { public void run() { textAreaScroller.scrollBy(0, 10); scheduleScroller(downScroller); } }; private Runnable upScroller = new Runnable() { public void run() { textAreaScroller.scrollBy(0, -10); scheduleScroller(upScroller); } }; private void scheduleScroller(Runnable scrollerJob) { Message msg = Message.obtain(mHandler, scrollerJob); msg.what = 1; mHandler.sendMessageDelayed(msg, 10); } private static Bitmap loadBitmapFromView(View v) { Bitmap b = Bitmap.createBitmap(400, 200, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); v.draw(c); return b; } private void loadDoc() { String s = ""; for (int x = 0; x <= 100; x++) { s += "Line: " + String.valueOf(x) + "\n"; } textView.setText(s); textView.setMovementMethod(new ScrollingMovementMethod()); } }
El problema es que una vez que desplazo TextView (trigger TouchEvent) el mapa de bits no refleja el contenido actual de TextView y en su lugar siempre tiene sólo el contenido inicial de TextView (no importa cuál es la posición de desplazamiento actual). He puesto al día la publicación para proporcionar código de trabajo – tal vez va a trabajar en el otro dispositivo sb.
ACTUALIZAR
También intenté comprobar la idea de onDraw
anulando onDraw
en mi TextView personalizado, pero de alguna manera todavía sólo dibujar el contenido de inicio de TextView:
public class MyTextView extends TextView { private Bitmap mBitmap; public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); } public MyTextView(Context context) { super(context); } public MyTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public Bitmap getBitmap() { return mBitmap; } @Override protected void onDraw(Canvas canvas) { mBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight() , Bitmap.Config.ARGB_8888); Canvas c = new Canvas(mBitmap); super.onDraw(canvas); super.onDraw(c); } }
- Android - Centro de vista de texto en LinearLayout
- El texto (fuente) parece desvanecido en los apis más antiguos
- ¿Es posible el estilo de los estilos de fuentes de Android con líder y el seguimiento?
- Android TextView no muestra Grabación de sonido Copyright símbolo "℗"
- ¿Cómo hacer clic o tocar en un texto TextView en diferentes palabras?
- Debe proporcionar un ID de recurso para un error de TextView android
- Nuevo Texto Seleccionable en el componente android 3 (API <= 11)
- Cómo obtener marcas de acento en las letras de un TextView Android
Intente anular el método onDraw()
de TextView
debería funcionar. Allí puede crear un mapa de bits basado en el parámetro canvas. Los detalles se pueden encontrar en mi tutorial: Cómo crear y guardar una captura de pantalla de un SurfaceView
Actualizar:
Solucioné tu problema:
La actividad (cambié el uso del manejador y quité algunos métodos. Básicamente encogí el código un poco).
import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.text.method.ScrollingMovementMethod; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.Button; import android.widget.ImageView; /** * @author WarrenFaith */ public class TextToImageActivity extends Activity { private MyTextView textView; private ImageView imageView; private boolean mRepeatDrawing = false; private Handler mHandler; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.textview); mHandler = new Handler(); imageView = (ImageView) findViewById(R.id.imageView); textView = (MyTextView) findViewById(R.id.scrapbook); Button upBtn = (Button) findViewById(R.id.upBtn); Button downBtn = (Button) findViewById(R.id.downBtn); upBtn.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { mRepeatDrawing = true; mHandler.post(upScroller); } else if (event.getAction() == MotionEvent.ACTION_UP) { mRepeatDrawing = false; } return false; } }); downBtn.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { mRepeatDrawing = true; mHandler.post(downScroller); } else if (event.getAction() == MotionEvent.ACTION_UP) { mRepeatDrawing = false; } return false; } }); loadDoc(); } private Runnable downScroller = new Runnable() { public void run() { textView.scrollBy(0, 10); imageView.setImageBitmap(textView.getBitmap()); if (mRepeatDrawing) { mHandler.postDelayed(this, 10); } } }; private Runnable upScroller = new Runnable() { public void run() { textView.scrollBy(0, -10); imageView.setImageBitmap(textView.getBitmap()); if (mRepeatDrawing) { mHandler.postDelayed(this, 10); } } }; private void loadDoc() { String s = ""; for (int x = 0; x <= 100; x++) { s += "Line: " + String.valueOf(x) + "\n"; } textView.setText(s); textView.setMovementMethod(new ScrollingMovementMethod()); } }
El texto personalizado: Importante: ¡el truco era conseguir la posición de desplazamiento!
import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.util.AttributeSet; import android.widget.TextView; /** * @author WarrenFaith */ public class MyTextView extends TextView { private Bitmap mBitmap; public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); } public MyTextView(Context context) { super(context); } public MyTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public Bitmap getBitmap() { return mBitmap; } @Override protected void onDraw(Canvas canvas) { mBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(mBitmap); c.translate(0, -getScrollY()); super.onDraw(c); super.onDraw(canvas); } }
El xml: (Quité el ScrollView y dejar que el TextView manejar el desplazamiento)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/parentLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <com.testproject.MyTextView android:id="@+id/scrapbook" android:layout_width="400px" android:layout_height="200px" android:scrollbars="vertical" android:scrollbarSize="3px" android:text="" android:background="#0000ff" /> <Button android:id="@+id/upBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Up" /> <Button android:id="@+id/downBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Down" /> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
- El contenido de los elementos debe consistir en datos de caracteres bien formados o marcado. AndroidManifest.xml
- ¿Cómo manipular los datos del cursor antes de mostrarlo en un ListView (usando un cargador)?