studio programacion herramientas fundamentos con avanzado aplicaciones android textview shadow

programacion - manual de android en pdf



TextView sombra destruida mientras captura la imagen (11)

La sombra se destruye al capturar la imagen de la vista de texto.

Agregué la sombra de texto mediante programación usando setShadowLayer.

tv.setShadowLayer(20, 0, 0, Color.BLACK);

cuando capturo la imagen usando

tv.buildDrawingCache(true); tv.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); tv.setDrawingCacheEnabled(true);

y obteniendo bitmap usando

bitmap = tv.getDrawingCache();

Imagen original en pantalla

Imagen capturada

También trató de capturar el diseño de los padres, pero el mismo resultado.


  1. Activa las aceleraciones de Android HW (agregando al manifiesto android:hardwareAccelerated="true" )
  2. Establezca una Vista para el tipo de capa LAYER_TYPE_SOFTWARE view.setLayerType(View.LAYER_TYPE_SOFTWARE,null) .

Intenta con estas dos cosas.


Así es como lo hice, pero necesitas root u otra fuente de capturas de pantalla. Aquí está el código java:

private TextView mTextView; private ImageView mImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) findViewById(R.id.t); mTextView.setShadowLayer(20, 0, 0, Color.BLACK); mImageView = (ImageView) findViewById(R.id.imageView); } public void onClick(View v) { Bitmap bitmap = getViewBitmap(mTextView); if (bitmap != null) { mImageView.setImageBitmap(bitmap); } } private int getRelativeLeft(View myView) { if (myView.getParent() == myView.getRootView()) return myView.getLeft(); else return myView.getLeft() + getRelativeLeft((View) myView.getParent()); } private int getRelativeTop(View myView) { if (myView.getParent() == myView.getRootView()) return myView.getTop(); else return myView.getTop() + getRelativeTop((View) myView.getParent()); } private Bitmap getViewBitmap(View view) { try { Process proc = Runtime.getRuntime().exec(new String[]{"su", "-c", "/system/bin/screencap -p"}); BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream())); Bitmap bitmap = BitmapFactory.decodeStream(proc.getInputStream()); String s; while ((s = stdError.readLine()) != null) { Log.i("log", s); } if (bitmap != null) { DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); bitmap = Bitmap.createBitmap(bitmap, getRelativeLeft(view), getRelativeTop(view), view.getMeasuredWidth(), view.getMeasuredHeight()); } return bitmap; } catch (IOException e) { e.printStackTrace(); } return null; }

Estoy usando screencap interno para obtener la captura de pantalla pero requiere root. Google creó una biblioteca para tomar capturas de pantalla sin root, por lo tanto, puedes usarla.


Captura la pantalla en mapa de bits y luego guárdala.

View screen = getWindow().getDecorView().getRootView(); screen.setDrawingCacheEnabled(true); Bitmap bitmap = Bitmap.createBitmap(screen.getDrawingCache()); screen.setDrawingCacheEnabled(false);


Después de crear bitmap llama a este

tv.setDrawingCacheEnabled(false);

después de este

bitmap = tv.getDrawingCache();


La diferencia entre las dos imágenes es que la imagen original se produce utilizando una capa LAYER_TYPE_HARDWARE . Cuando establece una capa de sombra en el texto con este tipo de capa, el procesador de gráficos crea una imagen borrosa en una textura.

Ver este artículo en Ver capas para más detalles.

La imagen capturada, por otro lado, se crea representando un mapa de bits, que es esencialmente el mismo que el uso de LAYER_TYPE_SOFTWARE . Dado que el procesador de gráficos ya no crea el desenfoque, no hay garantía de que se vea igual.

Puedes experimentar con ello. Agregue código para forzar la representación del software:

tv.setLayerType(View.LAYER_TYPE_SOFTWARE, null); tv.setShadowLayer(20, 0, 0, Color.BLACK);

Después de hacer esto, las dos imágenes se verán iguales.

Si desea que ambas imágenes se parezcan más a su imagen original con el desenfoque de hardware, puede ajustar el radio de desenfoque:

tv.setLayerType(View.LAYER_TYPE_SOFTWARE, null); tv.setShadowLayer(8, 0, 0, Color.BLACK);

Si desea obtener resultados exactamente como el original, al capturar un mapa de bits de la imagen renderizada en hardware, debe ser posible, pero no conozco una forma fácil. Es posible que tenga que volver a escribir la aplicación utilizando OpenGL para obtener acceso a los buffers de gráficos subyacentes.


Prueba este código, guarda lo que realmente aparece en la pantalla.

Bitmap bitmap = Bitmap.createBitmap(textView.getWidth(), textView.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); textView.draw(canvas); FileOutputStream var5; try { var5 = new FileOutputStream(new File(Environment.getExternalStorageDirectory(),"temp.png")); bitmap.compress(CompressFormat.PNG, 100, var5); var5.flush(); var5.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }

He probado con éxito.


Prueba esto,

La clase pública MainActivity extiende AppCompatActivity {

private TextView textView; private ImageView image; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Your text view textView = (TextView) findViewById(R.id.hello); textView.setShadowLayer(20, 0, 0, Color.BLACK); //Get bitmap from textView Bitmap customViewBitmap = createDrawableFromView(this, textView); //Set the bitmap to imageView image = (ImageView) findViewById(R.id.image); image.setImageBitmap(customViewBitmap); } public static Bitmap createDrawableFromView(Context context, View view) { DisplayMetrics displayMetrics = new DisplayMetrics(); ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels); view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels); view.buildDrawingCache(); Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); view.draw(canvas); return bitmap; } /* activity_main.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.pansapp.swipecard.MainActivity"> <TextView android:id="@+id/hello" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Hello World!" android:textSize="18sp" /> <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" /> </RelativeLayout> */

}


Puedes guardar cualquier vista como imagen de esta manera.

try { Bitmap mNewSaving = getBitmap(tv); String save_file = new File(dir, "View_" + System.currentTimeMillis() + ".png"); FileOutputStream mFileOutputStream = new FileOutputStream(save_file); mNewSaving.compress(Bitmap.CompressFormat.PNG, 95, mFileOutputStream); mFileOutputStream.flush(); mFileOutputStream.close(); } catch (FileNotFoundException e) { Log.v("hetal", "FileNotFoundExceptionError " + e.toString()); } catch (IOException e) { Log.v("hetal", "IOExceptionError " + e.toString()); }


Suponiendo que el búfer de hardware se utiliza si suministramos un mapa de bits al lienzo.

1) Anule Textview y cree su propio CustomTextview 2) Anule onMeasure y almacene el ancho y alto de Textview. 3) cree un mapa de bits del tamaño de la vista de texto para obtener el ancho y la altura de onMeasure. 4) sobrescribir onDraw (canvas) - canvas.setBitmap (bitmap) y llamar a super.ondraw ()

los datos se escriben en su mapa de bits, verifique el contenido


Esta (larga) respuesta aborda los problemas con la renderización y captura de hardware "Recuerde en Android que los gráficos están compuestos en la GPU. Por lo tanto, no hay razón para que la CPU tenga acceso a una copia de la imagen de pantalla compuesta completa, y a menudo no lo hace. " Así que tenemos que recurrir al código de captura de pantalla. Este problema se muestra aquí:

Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); view.draw(canvas);

view.draw debe usar View.LAYER_TYPE_SOFTWARE , por lo que no funcionará.

Un mejor intento es este (pero no funciona como los demás):

DisplayMetrics displayMetrics = new DisplayMetrics(); ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels); view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels); // Enabling the drawing cache is similar to setting a layer when hardware acceleration is turned off. // When hardware acceleration is turned on, // enabling the drawing cache has no effect on rendering because the system // uses a different mechanism for acceleration which ignores the flag. view.buildDrawingCache(); Bitmap b1 = view.getDrawingCache();//note no canvas, or draw // copy this bitmap otherwise destroying the cache will destroy // the bitmap for the referencing drawable and you''ll not // get the captured view Bitmap bitmap = b1.copy(Bitmap.Config.ARGB_8888, false); view.destroyDrawingCache();

"Si tienes root, por definición tienes todos los permisos de Android y, por lo tanto, puedes llamar a captureScreen API para obtener una imagen correcta".

Una de las nuevas API introducidas en Android 5.0 es la API de MediaProjection . De acuerdo con la documentación oficial, esta API nos permite capturar el contenido de la pantalla (sin root).

Consejo práctico:
Después de Android 4.0 "Ice Cream Sandwich", casi todos los teléfonos tienen captura de pantalla con el botón "apagar + bajar el volumen" presionado.


tv.buildDrawingCache(true); tv.setDrawingCacheQuality(View. DRAWING_CACHE_QUALITY_AUTO); tv.setDrawingCacheEnabled(true);