Cómo crear una barra de calificaciones personalizadas en Android

Hola, todo lo que necesito para realizar calificaciones en mi aplicación … Por lo tanto, necesito crear barras de calificación personalizadas … ¿Puede alguien ayudarme en esto?

Echa un vistazo a este post http://kozyr.zydako.net/2010/05/23/pretty-ratingbar/

Editar

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

Actualizado

Styles.xml

Esto debe encontrarse en la carpeta de valores

<?xml version="1.0" encoding="utf-8"?> <resources> <style name="foodRatingBar" parent="@android:style/Widget.RatingBar"> <item name="android:progressDrawable">@drawable/food_rating_bar_full</item> <item name="android:minHeight">23dip</item> <item name="android:maxHeight">25dip</item> </style> </resources> 

Food_rating_bar_full.xml

Este archivo debe estar en la carpeta Drawable.

  <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+android:id/background" android:drawable="@drawable/food_ratingbar_full_empty" /> <item android:id="@+android:id/secondaryProgress" android:drawable="@drawable/food_ratingbar_full_empty" /> <item android:id="@+android:id/progress" android:drawable="@drawable/food_ratingbar_full_filled" /> </layer-list> 

Food_ratingbar_full_empty.xml

Este archivo debe estar dentro de la carpeta Drawable.

 <?xml version="1.0" encoding="utf-8"?> <!-- This is the rating bar drawable that is used to show a filled cookie. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:state_window_focused="true" android:drawable="@drawable/cookiee" /> <item android:state_focused="true" android:state_window_focused="true" android:drawable="@drawable/cookiee" /> <item android:state_selected="true" android:state_window_focused="true" android:drawable="@drawable/cookiee" /> <item android:drawable="@drawable/cookiee" /> </selector> 

Food_ratingbar_full_filled.xml

Este archivo debe estar ubicado en la carpeta Drawable.

 <?xml version="1.0" encoding="utf-8"?> <!-- This is the rating bar drawable that is used to show a unfilled cookie. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:state_window_focused="true" android:drawable="@drawable/cookie" /> <item android:state_focused="true" android:state_window_focused="true" android:drawable="@drawable/cookie" /> <item android:state_selected="true" android:state_window_focused="true" android:drawable="@drawable/cookie" /> <item android:drawable="@drawable/cookie" /> </selector> 

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

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <RatingBar android:id="@+id/ratingBar1" style="@style/foodRatingBar" android:layout_width="wrap_content" android:layout_height="wrap_content"></RatingBar> </LinearLayout> 

MainActivity.class debería tener el siguiente aspecto:

 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 utilizado dos imágenes:

Cookie.jpg

Cookiee.jpg

Estas dos imágenes son del mismo tamaño que una se utiliza para identificar la barra de clasificación seleccionada y otra para identificar la barra de clasificación no seleccionada

Necesito agregar mi solución que es WAY eaiser que el anterior. Ni siquiera necesitamos usar estilos.

Cree un archivo selector en la carpeta dibujable:

Custom_ratingbar_selector.xml

 <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background" android:drawable="@drawable/star_off" /> <item android:id="@android:id/secondaryProgress" android:drawable="@drawable/star_off" /> <item android:id="@android:id/progress" android:drawable="@drawable/star_on" /> </layer-list> 

En el diseño de conjunto el archivo selector como progressDrawable:

  <RatingBar android:id="@+id/ratingBar2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="20dp" android:progressDrawable="@drawable/custom_ratingbar_selector" android:numStars="8" android:stepSize="0.2" android:rating="3.0" /> 

Y eso es todo lo que necesitamos.

Primero agregar imágenes a dibujable:

Introduzca aquí la descripción de la imagen Introduzca aquí la descripción de la imagen

La primera imagen "ratingbar_staroff.png" y la segunda "ratingbar_staron.png"

Después, cree "ratingbar.xml" en res / drawable

 <?xml version="1.0" encoding="utf-8"?> <!--suppress AndroidDomInspection --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+android:id/background" android:drawable="@drawable/ratingbar_empty" /> <item android:id="@+android:id/secondaryProgress" android:drawable="@drawable/ratingbar_empty" /> <item android:id="@+android:id/progress" android:drawable="@drawable/ratingbar_filled" /> </layer-list> 

El siguiente xml el mismo en res / drawable

"Ratingbar_empty.xml"

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:state_window_focused="true" android:drawable="@drawable/ratingbar_staroff" /> <item android:state_focused="true" android:state_window_focused="true" android:drawable="@drawable/ratingbar_staroff" /> <item android:state_selected="true" android:state_window_focused="true" android:drawable="@drawable/ratingbar_staroff" /> <item android:drawable="@drawable/ratingbar_staroff" /> </selector> 

"Ratingbar_filled"

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:state_window_focused="true" android:drawable="@drawable/ratingbar_staron" /> <item android:state_focused="true" android:state_window_focused="true" android:drawable="@drawable/ratingbar_staron" /> <item android:state_selected="true" android:state_window_focused="true" android:drawable="@drawable/ratingbar_staron" /> <item android:drawable="@drawable/ratingbar_staron" /> </selector> 

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

 <style name="CustomRatingBar" parent="@android:style/Widget.RatingBar"> <item name="android:progressDrawable">@drawable/ratingbar</item> <item name="android:minHeight">18dp</item> <item name="android:maxHeight">18dp</item> </style> 

Ahora, ya puede agregar estilo al recurso de ratingbar

  <RatingBar android:layout_width="wrap_content" android:layout_height="wrap_content" style= "@style/CustomRatingBar" android:id="@+id/ratingBar" android:numStars="5" android:stepSize="0.01" android:isIndicator="true"/> 

Finalmente en su actividad sólo es declarar:

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

Introduzca aquí la descripción de la imagen

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

SmileyRating

Introduzca aquí la descripción de la imagen

Hacer que la barra de calificación personalizada con la lista de capas y los 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 estado lleno png.

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 código siguiente 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); } 

Al crear una barra de calificación personalizada que muestra una línea de degradado sólido 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 erróneo dibujable que usé originalmente (que generó el problema), como sugiere el desarrollador de Android y otras entradas de StackOverflow:

 <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background" android:drawable="@drawable/seekbar_track"/> <item android:id="@android:id/secondaryProgress"> <scale android:drawable="@drawable/seekbar_progress2" android:scaleWidth="100%" /> </item> <item android:id="@android:id/progress" > <clip android:clipOrientation="horizontal" android:gravity="left" > <shape> <gradient android:startColor="@color/ratingbar_bg_start" android:centerColor="@color/ratingbar_bg_center" android:centerX="0.5" android:endColor="@color/ratingbar_bg_end" android:angle="0" /> </shape> </clip> </item> </layer-list> 

El problema aquí es el primer elemento, que se relaciona con el fondo de la custom RatingBar. Muchas entradas le indicarán que establezca la característica layout_minHeight en un valor grande para evitar una desconexión espacial vertical entre el pulgar y su pista. Esto no era la solución para mí – cuando se ve en una tableta, el fondo seguía dibujando a su menor tamaño basado en teléfono – por lo que la pista se colocó consistentemente bien por encima del centro de la pista RatingBar. La solución es eliminar esta entrada en la RatingBar dibujable, por lo que ahora se ve así:

 <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/secondaryProgress"> <scale android:drawable="@drawable/seekbar_progress2" android:scaleWidth="100%" /> </item> <item android:id="@android:id/progress" > <clip android:clipOrientation="horizontal" android:gravity="left" > <shape> <gradient android:startColor="@color/ratingbar_bg_start" android:centerColor="@color/ratingbar_bg_center" android:centerX="0.5" android:endColor="@color/ratingbar_bg_end" android:angle="0" /> </shape> </clip> </item> </layer-list> 

A continuación, en la definición de estilo de la barra de clasificación personalizada, establezca el layout_background a la pista dibujable. Mina se ve así:

 <style name="styleRatingBar" parent="@android:style/Widget.RatingBar"> <item name="android:indeterminateOnly">false</item> <item name="android:background">@drawable/seekbar_track</item> <item name="android:progressDrawable">@drawable/abratingbar</item> <item name="android:thumb">@drawable/abseekbar_thumb</item> <item name="android:minHeight">@dimen/base_29dp</item> <item name="android:maxHeight">@dimen/base_29dp</item> <item name="android:layout_marginLeft">@dimen/base_10dp</item> <item name="android:layout_marginRight">@dimen/base_10dp</item> <item name="android:layout_marginTop">@dimen/base_10dp</item> <item name="android:layout_marginBottom">@dimen/base_10dp</item> <item name="android:scaleType">fitXY</item> </style> 

(Anteriormente, el ajuste de fondo aquí era indefinido.).

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

 <RatingBar android:id="@+id/ratingbar_vote" style="@style/styleRatingBar" android:hint="@string/ratingbar_vote" android:contentDescription="@string/ratingbar_vote" android:numStars="5" android:rating="5" android:stepSize="1" android:layout_width="match_parent" android:layout_height="@dimen/base_29dp" android:layout_marginLeft="@dimen/base_120dp" android:layout_gravity="bottom|right" /> 

Por lo tanto, para resumir, no establezca la característica de fondo (pista) en su RatingBar personalizada dibujable, establezca en la característica layout_background de su estilo personalizado RatingBar. Esto asegura que la pista esté siempre centrada verticalmente en una barra Clasificadora horizontal. (Recuerde que en este Custom RatingBar, en lugar de utilizar estrellas u otras imágenes aisladas como la calificación, estoy usando una línea de degradado que "crece" o "se encoge" horizontalmente para mostrar la calificación – esta línea de calificación utiliza un pulgar similar a SeekBar Ejecutándose en una "pista" tipo SeekBar.)

Hice algo simular, un RatingBar con iconos de clasificación individuales, estoy usando VectorDrawables para los iconos de calificación, pero se puede utilizar cualquier tipo de drawable

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

Introduzca aquí la descripción de la imagen

Usted puede tener 5 imageview con la imagen del defalut como la estrella que es vacía y llenar la barra de la graduación con la mitad o la base completa de la imagen 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; } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.