Cómo crear una barra de calificaciones personalizadas en Android

Hola, todo lo que necesito para realizar calificaciones en mi aplicación … ASÍ QUE necesito crear una barra de calificaciones personalizada … ¿Alguien puede ayudarme en esto?

Editar

Eche un vistazo a la calificación personalizada en motorola http://community.developer.motorola.com/t5/Android-App-Development-for/custom-rate-bar-style-using-android-s-ratingBar-small-style/ td-p / 10462

Actualizado

styles.xml

Esto debe estar ubicado en su carpeta de valores

< ?xml version="1.0" encoding="utf-8"?>    

food_rating_bar_full.xml

Este archivo debe estar en la carpeta Drawable.

 < ?xml version="1.0" encoding="utf-8"?>      

food_ratingbar_full_empty.xml

Este archivo debe estar dentro de la carpeta Drawable.

 < ?xml version="1.0" encoding="utf-8"?>        

food_ratingbar_full_filled.xml

Este archivo debe estar ubicado en la carpeta Drawable.

 < ?xml version="1.0" encoding="utf-8"?>        

El archivo main.xml debería verse así:

 < ?xml version="1.0" encoding="utf-8"?>     

MainActivity.class debe verse así:

 import android.app.Activity; import android.os.Bundle; import android.widget.RatingBar; import android.widget.RatingBar.OnRatingBarChangeListener; import android.widget.Toast; public class MainActivity extends Activity { /** Called when the activity is first created. */ RatingBar rb; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); rb=(RatingBar)findViewById(R.id.ratingBar1); rb.setOnRatingBarChangeListener(new OnRatingBarChangeListener(){ @Override public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { // TODO Auto-generated method stub Toast.makeText(getApplicationContext(),Float.toString(rating),Toast.LENGTH_LONG).show(); } }); } } 

He usado dos imágenes:

cookie.jpg

cookiee.jpg

Estas dos imágenes son del mismo tamaño, una se usa para identificar la barra de calificación seleccionada y otra para identificar la barra de calificación no seleccionada.

Necesito agregar mi solución, que es mucho más segura que la anterior. Ni siquiera necesitamos usar estilos.

Crea un archivo selector en la carpeta dibujable:

custom_ratingbar_selector.xml

 < ?xml version="1.0" encoding="utf-8"?>      

En el diseño, establezca el archivo selector como progressDrawable:

   

Y eso es todo lo que necesitamos

primero agrega imágenes a dibujables:

enter image description here enter image description here

la primera imagen “ratingbar_staroff.png” y la segunda “ratingbar_staron.png”

Después, crea “ratingbar.xml” en res / dibujable

 < ?xml version="1.0" encoding="utf-8"?>       

el siguiente xml es el mismo en res / dibujable

“ratingbar_empty.xml”

 < ?xml version="1.0" encoding="utf-8"?>       

“ratingbar_filled”

 < ?xml version="1.0" encoding="utf-8"?>       

el siguiente en hacer, agregue estas líneas de código en res / values ​​/ styles

  

Ahora, ya puede agregar estilo al recurso de la barra de calificación

   

finalmente, en tu actividad solo se declara:

 RatingBar ratingbar = (RatingBar) findViewById(R.id.ratingbar); ratingbar.setRating(3.67f); 

enter image description here

Puedes probar esta barra de calificación con animaciones mucho mejores

SmileyRating

enter image description here

Hice algo simular, una RatingBar con icons de clasificación individual, estoy usando VectorDrawables para los icons de calificación pero podría usar cualquier tipo de dibujable

https://github.com/manmountain/emoji-ratingbar

enter image description here

Hacer que la barra de clasificación personalizada con la lista de capas y selectores sea compleja, es mejor anular la clase RatingBar y crear una RatingBar personalizada. createBackgroundDrawableShape () es la función donde debe poner su estado vacío png y createProgressDrawableShape () es la función donde debe poner su png de estado lleno.

Nota: Este código no funcionará con svg por ahora.

 public class CustomRatingBar extends RatingBar { @Nullable private Bitmap mSampleTile; public ShapeDrawableRatingBar(final Context context, final AttributeSet attrs) { super(context, attrs); setProgressDrawable(createProgressDrawable()); } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mSampleTile != null) { final int width = mSampleTile.getWidth() * getNumStars(); setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0), getMeasuredHeight()); } } protected LayerDrawable createProgressDrawable() { final Drawable backgroundDrawable = createBackgroundDrawableShape(); LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{ backgroundDrawable, backgroundDrawable, createProgressDrawableShape() }); layerDrawable.setId(0, android.R.id.background); layerDrawable.setId(1, android.R.id.secondaryProgress); layerDrawable.setId(2, android.R.id.progress); return layerDrawable; } protected Drawable createBackgroundDrawableShape() { final Bitmap tileBitmap = drawableToBitmap(getResources().getDrawable(R.drawable.ic_star_empty)); if (mSampleTile == null) { mSampleTile = tileBitmap; } final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape()); final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP); shapeDrawable.getPaint().setShader(bitmapShader); return shapeDrawable; } protected Drawable createProgressDrawableShape() { final Bitmap tileBitmap = drawableToBitmap(getResources().getDrawable(R.drawable.ic_star_full)); final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape()); final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP); shapeDrawable.getPaint().setShader(bitmapShader); return new ClipDrawable(shapeDrawable, Gravity.LEFT, ClipDrawable.HORIZONTAL); } Shape getDrawableShape() { final float[] roundedCorners = new float[]{5, 5, 5, 5, 5, 5, 5, 5}; return new RoundRectShape(roundedCorners, null, null); } public static Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } int width = drawable.getIntrinsicWidth(); width = width > 0 ? width : 1; int height = drawable.getIntrinsicHeight(); height = height > 0 ? height : 1; final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } } 

El siguiente código funciona:

 @Override protected synchronized void onDraw(Canvas canvas) { int stars = getNumStars(); float rating = getRating(); try { bitmapWidth = getWidth() / stars; } catch (Exception e) { bitmapWidth = getWidth(); } float x = 0; for (int i = 0; i < stars; i++) { Bitmap bitmap; Resources res = getResources(); Paint paint = new Paint(); if ((int) rating > i) { bitmap = BitmapFactory.decodeResource(res, starColor); } else { bitmap = BitmapFactory.decodeResource(res, starDefault); } Bitmap scaled = Bitmap.createScaledBitmap(bitmap, getHeight(), getHeight(), true); canvas.drawBitmap(scaled, x, 0, paint); canvas.save(); x += bitmapWidth; } super.onDraw(canvas); } 

Puede crear una barra de clasificación de material personalizada definiendo xml dibujable utilizando el icono de material de su elección y luego aplicando dibujo personalizable a la barra de clasificación usando el atributo progressDrawable.

Para obtener información sobre la personalización de la barra de clasificación, consulte http://www.zoftino.com/android-ratingbar-and-custom-ratingbar-example

A continuación, el xml dibuja utiliza el ícono de los pulgares arriba para la barra de calificación.

 < ?xml version="1.0" encoding="utf-8"?>            

Al crear una barra de clasificación personalizada que muestra una línea de degradado sólida que se ejecuta en una pista similar a SeekBar, en lugar de estrellas, también encontré un problema relacionado con el centrado vertical del fondo (pista dibujable). Este es el código drawable defectuoso que utilicé originalmente (que generó el problema), según lo sugerido por el desarrollador de Android y otras entradas de StackOverflow:

 < ?xml version="1.0" encoding="utf-8"?>              

El problema aquí es el primer elemento, que se relaciona con los antecedentes de la Barra de calificación personalizada. Muchas entradas le indicarán que configure la característica layout_minHeight en algún valor grande para evitar una desconexión espacial vertical entre el pulgar y su pista. Esta no era la solución para mí: cuando se veía en una tableta, el fondo todavía se estaba enfocando en su tamaño más pequeño basado en el teléfono, por lo que la pista se posicionaba consistentemente bien arriba del centro de la pista de la Barra de Clasificación. La solución es eliminar esta entrada en el drawable de RatingBar, por lo que ahora se ve así:

 < ?xml version="1.0" encoding="utf-8"?>             

Luego, en la definición de estilo de la Barra de clasificación personalizada, establezca el layout_background en la pista dibujable. El mío se ve así:

  

(Anteriormente, la configuración de fondo aquí no estaba definida).

Esta es la entrada en mi diseño, que utiliza tanto el estilo como los elementos dibujables:

  

Por lo tanto, para resumir, no establezca la función de fondo (seguimiento) en su Drawbar de RatingBar personalizado, configúrelo en la función layout_background de su estilo personalizado de RatingBar. Esto asegura que la pista esté siempre centrada verticalmente en una barra de clasificación horizontal. (Recuerde, en esta CustomBar personalizada, en lugar de usar estrellas u otras imágenes aisladas como calificación, estoy usando una línea de degradado que “crece” o “contrae” horizontalmente para mostrar la calificación; esta línea de calificación utiliza un pulgar tipo SeekBar corriendo en una “pista” parecida a SeekBar).

Puede usar la solución dada de @erdomester para esto. Pero si enfrenta problemas con la altura de la barra de clasificación, entonces puede usar la altura de los icons de la barra de calificación mediante progtwigción.

En Kotlin,

 val drawable = ContextCompat.getDrawable(context, R.drawable.rating_filled) val drawableHeight = drawable.intrinsicHeight rating_bar.layoutParams.height = drawableHeight 

Puede tener 5 imágenes con imagen de defalut como estrella que está vacía y llenar la barra de clasificación con la mitad o la base de la imagen completa en la calificación.

  public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View grid=inflater.inflate(R.layout.griditem, parent, false); imageView=(ImageView)grid.findViewById(R.id.grid_prod); imageView.setImageResource(imgId[position]); imgoff =(ImageView)grid.findViewById(R.id.offer); tv=(TextView)grid.findViewById(R.id.grid_text); tv.setText(namesArr[position]); tv.setTextColor(Color.BLACK); tv.setPadding(0, 2, 0, 0); sta=(ImageView)grid.findViewById(R.id.imageView); sta1=(ImageView)grid.findViewById(R.id.imageView1); sta2=(ImageView)grid.findViewById(R.id.imageView2); sta3=(ImageView)grid.findViewById(R.id.imageView3); sta4=(ImageView)grid.findViewById(R.id.imageView4); Float rate=rateFArr[position]; if(rate==5 || rate==4.5) { sta.setImageResource(R.drawable.full__small); sta1.setImageResource(R.drawable.full__small); sta2.setImageResource(R.drawable.full__small); sta3.setImageResource(R.drawable.full__small); if(rate==4.5) { sta4.setImageResource(R.drawable.half_small); } else { sta4.setImageResource(R.drawable.full__small); } } if(rate==4 || rate==3.5) { sta.setImageResource(R.drawable.full__small); sta1.setImageResource(R.drawable.full__small); sta2.setImageResource(R.drawable.full__small); if(rate==3.5) { sta3.setImageResource(R.drawable.half_small); } else { sta3.setImageResource(R.drawable.full__small); } } if(rate==3 || rate==2.5) { sta.setImageResource(R.drawable.full__small); sta1.setImageResource(R.drawable.full__small); if(rate==2.5) { sta2.setImageResource(R.drawable.half_small); } else { sta2.setImageResource(R.drawable.full__small); } } if(rate==2 || rate==1.5) { sta.setImageResource(R.drawable.full__small); if(rate==1.5) { sta1.setImageResource(R.drawable.half_small); } else { sta1.setImageResource(R.drawable.full__small); } } if(rate==1 || rate==0.5) { if(rate==1) sta.setImageResource(R.drawable.full__small); else sta.setImageResource(R.drawable.half_small); } if(rate>5) { sta.setImageResource(R.drawable.full__small); sta1.setImageResource(R.drawable.full__small); sta2.setImageResource(R.drawable.full__small); sta3.setImageResource(R.drawable.full__small); sta4.setImageResource(R.drawable.full__small); } // rb=(RatingBar)findViewById(R.id.grid_rating); //rb.setRating(rateFArr[position]); return grid; }