Android custom rating bar example

attrs.xml, the custom attributes for the custom rating bar, create this file if it doesn’t exist already, place it in the values directory.



    
        
        
        
    

The style for the custom rating bar.


CustomRatingBar.java, the implementation of the custom rating bar. It extends the LinearLayout, populates star images from vector drawables.

/*
 * Copyright (c) 2016 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.content.res.ResourcesCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.widget.ImageView;
import android.widget.LinearLayout;


/**
 * Replacement for a {@link android.widget.RatingBar} widget for providing ratings for sessions.
 * Provides ease of use for accessibility for use with Talkback and other assistive technologies.
 * 

* TODO: add explanation of attributes. */ public class CustomRatingBar extends LinearLayout implements View.OnClickListener { /** * The default maximum rating value if no specific value is specified. */ private static final int DEFAULT_MAX_RATING = 5; /** * The drawable used if no unfilled drawable resource is specified. */ private static final int DEFAULT_UNFILLED_DRAWABLE_ID = R.drawable.ic_star_empty; /** * The drawable used if no filled drawable resource is specified. */ private static final int DEFAULT_FILLED_DRAWABLE_ID = R.drawable.ic_star_filled; /** * The maximum permitted rating. */ private int mMaxRating; /** * The {@link Drawable} used to show a filled value. A rating of M out of N stars is * represented by M filled drawables and N - M unfilled drawables. */ private Drawable mFilledDrawable; /** * The {@link Drawable} used to show an unfilled value. A rating of M out of N stars is * represented by M filled drawables and N - M unfilled drawables. */ private Drawable mUnfilledDrawable; /** * The rating specified by the user. */ private int mRating = 0; public CustomRatingBar(Context context) { this(context, null, 0); } public CustomRatingBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomRatingBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray typedArray = context.getTheme().obtainStyledAttributes( attrs, R.styleable.CustomRatingBar, 0, 0); try { mMaxRating = typedArray.getInt(R.styleable.CustomRatingBar_maxRating, DEFAULT_MAX_RATING); mFilledDrawable = typedArray.getDrawable(R.styleable.CustomRatingBar_filledDrawable); if (mFilledDrawable == null) { mFilledDrawable = ResourcesCompat.getDrawable(getResources(), DEFAULT_FILLED_DRAWABLE_ID, null); } mUnfilledDrawable = typedArray.getDrawable(R.styleable.CustomRatingBar_unfilledDrawable); if (mUnfilledDrawable == null) { mUnfilledDrawable = ResourcesCompat.getDrawable(getResources(), DEFAULT_UNFILLED_DRAWABLE_ID, null); } } finally { typedArray.recycle(); } setSaveEnabled(true); } public int getRating() { return mRating; } @Override public void onClick(final View v) { mRating = (int) v.getTag(); drawRatingViews(); int eventType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN ? AccessibilityEvent.TYPE_ANNOUNCEMENT : AccessibilityEvent.TYPE_VIEW_FOCUSED; sendAccessibilityEvent(eventType); } @Override protected void onFinishInflate() { super.onFinishInflate(); drawRatingViews(); } @Override public void sendAccessibilityEvent(final int eventType) { if (!AccessibilityUtils.isAccessibilityEnabled(getContext())) { return; } super.sendAccessibilityEvent(eventType); AccessibilityEvent event = AccessibilityEvent.obtain(eventType); // Get the Talkback text. event.getText().add(getContext().getResources().getString( R.string.feedback_rating_confirmation, mRating, mMaxRating)); event.setEnabled(true); AccessibilityManager accessibilityManager = (AccessibilityManager) getContext() .getSystemService(Context.ACCESSIBILITY_SERVICE); accessibilityManager.sendAccessibilityEvent(event); } /** * Creates or updates the views used for creating a rating. */ private void drawRatingViews() { if (this.getChildCount() == 0) { createRatingViews(); } else { updateRatingViews(); } } /** * Creates ({@link ImageView}s) used to submit a rating using unfilled drawables and adds them to * the layout. */ private void createRatingViews() { for (int i = 0; i < mMaxRating; i++) { ImageView imageView = new ImageView(getContext()); imageView.setLayoutParams( new android.view.ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); int tagValue = i + 1; imageView.setTag(tagValue); imageView.setContentDescription(getContext().getString( R.string.feedback_rating_value, tagValue)); imageView.setImageDrawable(mUnfilledDrawable); imageView.setOnClickListener(this); addView(imageView); } } /** * Updates ({@link ImageView}s) used to submit a rating, using filled drawables to denote the * rating created by the user. */ private void updateRatingViews() { for (int i = 0; i < mMaxRating; i++) { ImageView view = (ImageView) this.getChildAt(i); view.setImageDrawable(i + 1 <= mRating ? mFilledDrawable : mUnfilledDrawable); } } @Override protected Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState savedState = new SavedState(superState); savedState.rating = mRating; return savedState; } @Override protected void onRestoreInstanceState(final Parcelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); mRating = ss.rating; drawRatingViews(); } /** * Helper class to help retain state during orientation change. */ private static class SavedState extends BaseSavedState { int rating; SavedState(Parcelable superState) { super(superState); } private SavedState(Parcel in) { super(in); rating = in.readInt(); } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeInt(rating); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } }

Using the custom ratingbar in a layout file.




    


Complete example in Github

Search within Codexpedia

Custom Search

Search the entire web

Custom Search