Hallo, alles was ich brauche, um Bewertungen in meiner Anwendung durchzuführen ... SO muss ich eine benutzerdefinierte Bewertungsleiste erstellen ... Kann mir jemand dabei helfen?
Hallo, alles was ich brauche, um Bewertungen in meiner Anwendung durchzuführen ... SO muss ich eine benutzerdefinierte Bewertungsleiste erstellen ... Kann mir jemand dabei helfen?
Antworten:
Bearbeiten
Werfen Sie einen Blick auf die benutzerdefinierte Bewertung in Motorola http://community.developer.motorola.com/t5/Android-App-Development-for/custom-rating-bar-style-using-android-s-ratingBar-small-style/ td-p / 10462
Aktualisiert
styles.xml
Dies muss sich in Ihrem Werteordner befinden
<?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
Diese Datei muss sich im Ordner Drawable befinden.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/background"
android:drawable="@drawable/food_ratingbar_full_empty" />
<item android:id="@+id/secondaryProgress"
android:drawable="@drawable/food_ratingbar_full_empty" />
<item android:id="@+id/progress"
android:drawable="@drawable/food_ratingbar_full_filled" />
</layer-list>
food_ratingbar_full_empty.xml
Diese Datei muss sich im Ordner Drawable befinden.
<?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
Diese Datei muss sich im Ordner Drawable befinden.
<?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>
Die Datei main.xml sollte folgendermaßen aussehen:
<?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 sollte folgendermaßen aussehen:
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();
}
});
}
}
Ich habe zwei Bilder verwendet:
cookie.jpg
cookiee.jpg
Diese beiden Bilder haben dieselbe Größe. Eines dient zur Identifizierung der ausgewählten Bewertungsleiste und das andere zur Identifizierung der nicht ausgewählten Bewertungsleiste
Ich muss meine Lösung hinzufügen, die viel einfacher ist als die oben genannte. Wir müssen nicht einmal Stile verwenden.
Erstellen Sie eine Auswahldatei im Zeichenordner:
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>
Legen Sie im Layout die Auswahldatei als progressDrawable fest:
<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" />
Und das ist alles was wir brauchen.
Fügen Sie zuerst Bilder zum Zeichnen hinzu:
das erste Bild "Ratingbar_staroff.png" und das zweite "Ratingbar_staron.png"
Erstellen Sie anschließend "reviewbar.xml" auf 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>
die nächste xml gleich auf 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>
"bewertungsleiste_gefüllt"
<?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>
Fügen Sie als Nächstes diese Codezeilen in res / values / styles hinzu
<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>
Jetzt kann der Ressourcen der Bewertungsleiste bereits Stil hinzugefügt werden
<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"/>
Schließlich wird auf Ihrer Aktivität nur erklärt:
RatingBar ratingbar = (RatingBar) findViewById(R.id.ratingbar);
ratingbar.setRating(3.67f);
res/values/styleser definiert android:minHeightund android:maxHeightändert, um
Das Erstellen der benutzerdefinierten Bewertungsleiste mit Ebenenliste und Selektoren ist komplex. Es ist besser, die RatingBar-Klasse zu überschreiben und eine benutzerdefinierte Bewertungsleiste zu erstellen. createBackgroundDrawableShape () ist die Funktion, in die Sie Ihren leeren Status png einfügen sollten, und createProgressDrawableShape () ist die Funktion, in die Sie Ihren gefüllten Status png einfügen sollten.
Hinweis: Dieser Code funktioniert derzeit nicht mit svg.
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;
}
}
Für SVG habe RatingBar ich die benutzerdefinierte Überlagerung von RatingBar-benutzerdefinierten Vektorzeichnungen und die Antwort von erdomester hier verwendet. Diese Lösung durchläuft alle Drawables in der SvgRatingBarInnenansicht Ihres Layouts, sodass RecyclerViewein Overhead entsteht.
SvgRatingBar.java:
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.VectorDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.graphics.drawable.shapes.Shape;
import android.os.Build;
import android.util.AttributeSet;
import android.view.Gravity;
import androidx.appcompat.graphics.drawable.DrawableWrapper;
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
import com.example.R; // Your R.java file for R.attr.ratingBarStyle.
public class SvgRatingBar extends androidx.appcompat.widget.AppCompatRatingBar {
private Bitmap sampleTile;
public SvgRatingBar(Context context) {
this(context, null);
}
public SvgRatingBar(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.ratingBarStyle);
}
public SvgRatingBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
LayerDrawable drawable = (LayerDrawable) createTile(getProgressDrawable(), false);
setProgressDrawable(drawable);
}
/**
* Converts a drawable to a tiled version of itself. It will recursively
* traverse layer and state list drawables.
*/
@SuppressLint("RestrictedApi")
private Drawable createTile(Drawable drawable, boolean clip) {
if (drawable instanceof DrawableWrapper) {
Drawable inner = ((DrawableWrapper) drawable).getWrappedDrawable();
if (inner != null) {
inner = createTile(inner, clip);
((DrawableWrapper) drawable).setWrappedDrawable(inner);
}
} else if (drawable instanceof LayerDrawable) {
LayerDrawable background = (LayerDrawable) drawable;
final int n = background.getNumberOfLayers();
Drawable[] outDrawables = new Drawable[n];
for (int i = 0; i < n; i++) {
int id = background.getId(i);
outDrawables[i] = createTile(background.getDrawable(i),
(id == android.R.id.progress || id == android.R.id.secondaryProgress));
}
LayerDrawable newBg = new LayerDrawable(outDrawables);
for (int i = 0; i < n; i++) {
newBg.setId(i, background.getId(i));
}
return newBg;
} else if (drawable instanceof BitmapDrawable) {
final BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
final Bitmap tileBitmap = bitmapDrawable.getBitmap();
if (sampleTile == null) {
sampleTile = tileBitmap;
}
final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
shapeDrawable.getPaint().setShader(bitmapShader);
shapeDrawable.getPaint().setColorFilter(bitmapDrawable.getPaint().getColorFilter());
return (clip) ? new ClipDrawable(shapeDrawable, Gravity.START,
ClipDrawable.HORIZONTAL) : shapeDrawable;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && drawable instanceof VectorDrawable) {
return createTile(getBitmapDrawableFromVectorDrawable(drawable), clip);
} else if (drawable instanceof VectorDrawableCompat) {
// API 19 support.
return createTile(getBitmapDrawableFromVectorDrawable(drawable), clip);
}
return drawable;
}
private BitmapDrawable getBitmapDrawableFromVectorDrawable(Drawable drawable) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return new BitmapDrawable(getResources(), bitmap);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (sampleTile != null) {
final int width = sampleTile.getWidth() * getNumStars();
setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0),
getMeasuredHeight());
}
}
private Shape getDrawableShape() {
final float[] roundedCorners = new float[]{5, 5, 5, 5, 5, 5, 5, 5};
return new RoundRectShape(roundedCorners, null, null);
}
}
In Ihrem Layout:
<com.example.common.control.SvgRatingBar
android:id="@+id/rate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="13dp"
android:numStars="5"
android:progressDrawable="@drawable/rating_bar"
android:rating="3.5"
android:stepSize="0.01"
/>
Sie müssen außerdem grade_bar.xml mit zwei SVG-Drawables erstellen:
<?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/ic_unfilled_star"
/>
<item
android:id="@android:id/secondaryProgress"
android:drawable="@drawable/ic_unfilled_star"
/>
<item
android:id="@android:id/progress"
android:drawable="@drawable/ic_filled_star"
/>
</layer-list>
Wenn in der Ansicht Design / Split nur ein Stern angezeigt wird, aktualisieren Sie das Layout:
In Kotlin.
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapShader
import android.graphics.Canvas
import android.graphics.Shader
import android.graphics.drawable.*
import android.graphics.drawable.shapes.RoundRectShape
import android.os.Build
import android.util.AttributeSet
import android.view.Gravity
import androidx.appcompat.graphics.drawable.DrawableWrapper
import androidx.appcompat.widget.AppCompatRatingBar
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
import com.example.R; // Your R.java file for R.attr.ratingBarStyle.
class SvgRatingBar @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
defStyleAttr: Int = R.attr.ratingBarStyle) :
AppCompatRatingBar(context, attrs, defStyleAttr) {
private var sampleTile: Bitmap? = null
private val roundedCorners = floatArrayOf(5f, 5f, 5f, 5f, 5f, 5f, 5f, 5f)
private val roundRectShape = RoundRectShape(roundedCorners, null, null)
init {
progressDrawable = createTile(progressDrawable, false) as LayerDrawable
}
/**
* Converts a drawable to a tiled version of itself. It will recursively
* traverse layer and state list drawables.
*/
private fun createTile(drawable: Drawable, clip: Boolean): Drawable =
when {
drawable is DrawableWrapper -> {
@SuppressLint("RestrictedApi")
var inner = drawable.wrappedDrawable
if (inner != null) {
inner = createTile(inner, clip)
@SuppressLint("RestrictedApi")
drawable.wrappedDrawable = inner
}
drawable
}
drawable is LayerDrawable -> {
val n = drawable.numberOfLayers
val outDrawables = arrayOfNulls<Drawable>(n)
for (i in 0 until n) {
val id = drawable.getId(i)
outDrawables[i] = createTile(drawable.getDrawable(i),
id == android.R.id.progress || id == android.R.id.secondaryProgress)
}
val newBg = LayerDrawable(outDrawables)
for (i in 0 until n) {
newBg.setId(i, drawable.getId(i))
}
newBg
}
drawable is BitmapDrawable -> {
val tileBitmap = drawable.bitmap
if (sampleTile == null) {
sampleTile = tileBitmap
}
val bitmapShader = BitmapShader(tileBitmap, Shader.TileMode.REPEAT,
Shader.TileMode.CLAMP)
val shapeDrawable = ShapeDrawable(roundRectShape).apply {
paint.shader = bitmapShader
paint.colorFilter = drawable.paint.colorFilter
}
if (clip) ClipDrawable(shapeDrawable, Gravity.START, ClipDrawable.HORIZONTAL)
else shapeDrawable
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && drawable is VectorDrawable -> {
createTile(getBitmapDrawableFromVectorDrawable(drawable), clip)
}
drawable is VectorDrawableCompat -> {
// Pre-Lollipop support.
createTile(getBitmapDrawableFromVectorDrawable(drawable), clip)
}
else -> drawable
}
private fun getBitmapDrawableFromVectorDrawable(drawable: Drawable): BitmapDrawable {
val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight,
Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
return BitmapDrawable(resources, bitmap)
}
@Synchronized override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
if (sampleTile != null) {
val width = sampleTile!!.width * numStars
setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0),
measuredHeight)
}
}
}
Ich habe die Originalquelle untersucht
und hier ist mein Ergebnis.
styles.xml (res / values)
<!-- RatingBar -->
<style name="RatingBar" parent="@android:style/Widget.RatingBar">
<item name="android:progressDrawable">@drawable/ratingbar_full</item>
<item name="android:indeterminateDrawable">@drawable/ratingbar_full</item>
<item name="android:minHeight">13.4dp</item>
<item name="android:maxHeight">13.4dp</item>
</style>
Ratingbar_full.xml (res / 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/btn_rating_star_off_normal" />
<item android:id="@android:id/secondaryProgress" android:drawable="@drawable/btn_rating_star_off_normal" />
<item android:id="@android:id/progress" android:drawable="@drawable/btn_rating_star_on_normal" />
</layer-list>
btn_rating_star_off_normal.png (res / drawable-xxhdpi)
btn_rating_star_on_normal.png (res / drawable-xxhdpi)
activity_ratingbar.xml (res / layout)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatRatingBar
android:id="@+id/ratingbar"
style="@style/RatingBar"
android:layout_width="wrap_content"
android:layout_height="13.4dp"
android:isIndicator="false"
android:numStars="5"
android:rating="2.6"
android:secondaryProgressTint="#00000000"
android:stepSize="0.1" />
</FrameLayout>
Das ist das Ergebnis.
layout_heightEigenschaft hinzugefügt habe , da in diesem Fall wrap_contentLinien unter den Sternen gezeichnet werden. (in meinem Fall nur in einer Vorschau von Android Studio)Ich habe etwas Ähnliches gemacht, eine Bewertungsleiste mit einzelnen Bewertungssymbolen. Ich verwende VectorDrawables für die Bewertungssymbole, aber Sie können jede Art von Zeichenelement verwenden
Der folgende Code funktioniert:
@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);
}
Sie können eine benutzerdefinierte Materialbewertungsleiste erstellen, indem Sie eine zeichnbare XML mithilfe des Materialsymbols Ihrer Wahl definieren und anschließend mithilfe des Attributs progressDrawable eine benutzerdefinierte Zeichenleiste auf die Bewertungsleiste anwenden.
Informationen zum Anpassen der Bewertungsleiste finden Sie unter http://www.zoftino.com/android-ratingbar-and-custom-ratingbar-example
Unterhalb der zeichnbaren XML wird das Daumen hoch-Symbol für die Bewertungsleiste verwendet.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<bitmap
android:src="@drawable/thumb_up"
android:tint="?attr/colorControlNormal" />
</item>
<item android:id="@android:id/secondaryProgress">
<bitmap
android:src="@drawable/thumb_up"
android:tint="?attr/colorControlActivated" />
</item>
<item android:id="@android:id/progress">
<bitmap
android:src="@drawable/thumb_up"
android:tint="?attr/colorControlActivated" />
</item>
</layer-list>
Beim Erstellen einer benutzerdefinierten Bewertungsleiste, die eine durchgezogene Verlaufslinie auf einer SeekBar-ähnlichen Spur anstelle von Sternen anzeigt, ist auch ein Problem im Zusammenhang mit der vertikalen Zentrierung des Hintergrunds aufgetreten (Spur zeichnbar). Dies ist der fehlerhafte Zeichencode, den ich ursprünglich verwendet habe (der das Problem verursacht hat), wie vom Android-Entwickler und anderen StackOverflow-Einträgen vorgeschlagen:
<?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>
Das Problem hierbei ist das erste Element, das sich auf den Hintergrund der benutzerdefinierten Bewertungsleiste bezieht. In vielen Einträgen werden Sie aufgefordert, die Funktion layout_minHeight auf einen großen Wert zu setzen, um eine vertikale räumliche Trennung zwischen Daumen und Spur zu vermeiden. Dies war nicht die Lösung für mich - wenn ich es auf einem Tablet betrachtete, zeichnete sich der Hintergrund immer noch auf seine kleinere telefonbasierte Größe ab -, sodass die Spur durchweg weit über der Mitte der RatingBar-Spur positioniert war. Die Lösung besteht darin, diesen Eintrag in der ausziehbaren Ratingleiste zu entfernen, sodass er jetzt folgendermaßen aussieht:
<?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>
Setzen Sie dann in der Stildefinition der benutzerdefinierten Bewertungsleiste den layout_background auf die zu zeichnende Spur. Meins sieht so aus:
<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>
(Bisher war die Hintergrundeinstellung hier undefiniert.)
Dies ist der Eintrag in meinem Layout, der sowohl den Stil als auch die Zeichen verwendet:
<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" />
Zusammenfassend lässt sich sagen, dass Sie die Hintergrund- (Spur-) Funktion nicht in Ihrer benutzerdefinierten RatingBar-Zeichnungsfunktion festlegen, sondern in der layout_background-Funktion Ihres benutzerdefinierten RatingBar-Stils. Dadurch wird sichergestellt, dass die Spur in einer horizontalen Bewertungsleiste immer vertikal zentriert ist. (Denken Sie daran, dass ich in dieser benutzerdefinierten Bewertungsleiste anstelle von Sternen oder anderen isolierten Bildern als Bewertung eine Verlaufslinie verwende, die horizontal "wächst" oder "schrumpft", um die Bewertung anzuzeigen. Diese Bewertungslinie verwendet einen SeekBar-ähnlichen Daumen Laufen auf einer SeekBar-ähnlichen "Spur".)
Sie können hierfür die von @erdomester angegebene Lösung verwenden. Wenn Sie jedoch Probleme mit der Höhe der Bewertungsleiste haben, können Sie die Höhe der Symbole der Bewertungsleiste programmgesteuert verwenden.
In Kotlin,
val drawable = ContextCompat.getDrawable(context, R.drawable.rating_filled)
val drawableHeight = drawable.intrinsicHeight
rating_bar.layoutParams.height = drawableHeight
android:minHeightim Layout hinzugefügt . Wenn Sie programmgesteuert ändern, sollten Sie hinzufügen rating_bar.requestLayout().
Sie können 5 Bildansichten mit defalutem Bild als Stern haben, der leer ist, und die Bewertungsleiste mit der halben oder vollen Bildbasis basierend auf der Bewertung füllen.
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;
}
RatingBarWidget. Auch das fragt das OP nicht.