2014-10-27 4 views
6

Sto cercando un modo semplice per implementare una barra di stato "stato" in Android come mostrato nei tre esempi di seguito. Dato che non sono un fan del reinventare la ruota, vorrei chiedere se c'è qualche biblioteca disponibile che non conosco.Stato progressbar android

L'ho cercato e non ho trovato nessuna libreria quindi suppongo di doverlo implementare da solo. Quale sarebbe la soluzione più semplice per farlo? Dovrei estendere ProgressBar o dovrei farlo da zero? Hai qualche suggerimento o tutorial su cui potrei accumulare?

Desired Progressbar

enter image description here

enter image description here

+0

Vedi qui: http: //stackoverflow.com/questions/14472144/how-to -fare-segmentato-SeekBar-cursore-look -come-following. È una barra di ricerca, ma puoi facilmente disabilitare gli utenti modificando il valore di ricerca. Dovrai anche cambiare lo stile ovviamente, ma la libreria sottostante è open source e flessibile: https://github.com/karabaralex/android-comboseekbar – kha

risposta

12

Aggiornamento

Si prega di vedere il this sample project, anche GIF è collegato a dare panoramica.

GIF Picture

È possibile personalizzare le seguenti operazioni per il vostro requisito.

Progress

import android.content.Context; 
import android.content.res.TypedArray; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.RectF; 
import android.os.Bundle; 
import android.os.Parcelable; 
import android.util.AttributeSet; 
import android.view.View; 

public class NumberProgressBar extends View { 

    private Context mContext; 

    /** 
    * The max progress, default is 100 
    */ 
    private int mMax = 100; 

    /** 
    * current progress, can not exceed the max progress. 
    */ 
    private int mProgress = 0; 

    /** 
    * the progress area bar color 
    */ 
    private int mReachedBarColor; 

    /** 
    * the bar unreached area color. 
    */ 
    private int mUnreachedBarColor; 

    /** 
    * the progress text color. 
    */ 
    private int mTextColor; 

    /** 
    * the progress text size 
    */ 
    private float mTextSize; 

    /** 
    * the height of the reached area 
    */ 
    private float mReachedBarHeight; 

    /** 
    * the height of the unreached area 
    */ 
    private float mUnreachedBarHeight; 

    /** 
    * the suffix of the number. 
    */ 
    private String mSuffix = "%"; 

    /** 
    * the prefix. 
    */ 
    private String mPrefix = ""; 


    private final int default_text_color = Color.rgb(66, 145, 241); 
    private final int default_reached_color = Color.rgb(66,145,241); 
    private final int default_unreached_color = Color.rgb(204, 204, 204); 
    private final float default_progress_text_offset; 
    private final float default_text_size; 
    private final float default_reached_bar_height; 
    private final float default_unreached_bar_height; 

    /** 
    * for save and restore instance of progressbar. 
    */ 
    private static final String INSTANCE_STATE = "saved_instance"; 
    private static final String INSTANCE_TEXT_COLOR = "text_color"; 
    private static final String INSTANCE_TEXT_SIZE = "text_size"; 
    private static final String INSTANCE_REACHED_BAR_HEIGHT = "reached_bar_height"; 
    private static final String INSTANCE_REACHED_BAR_COLOR = "reached_bar_color"; 
    private static final String INSTANCE_UNREACHED_BAR_HEIGHT = "unreached_bar_height"; 
    private static final String INSTANCE_UNREACHED_BAR_COLOR = "unreached_bar_color"; 
    private static final String INSTANCE_MAX = "max"; 
    private static final String INSTANCE_PROGRESS = "progress"; 
    private static final String INSTANCE_SUFFIX = "suffix"; 
    private static final String INSTANCE_PREFIX = "prefix"; 
    private static final String INSTANCE_TEXT_VISBILITY = "text_visibility"; 

    private static final int PROGRESS_TEXT_VISIBLE = 0; 
    private static final int PROGRESS_TEXT_INVISIBLE = 1; 



    /** 
    * the width of the text that to be drawn 
    */ 
    private float mDrawTextWidth; 

    /** 
    * the drawn text start 
    */ 
    private float mDrawTextStart; 

    /** 
    *the drawn text end 
    */ 
    private float mDrawTextEnd; 

    /** 
    * the text that to be drawn in onDraw() 
    */ 
    private String mCurrentDrawText; 

    /** 
    * the Paint of the reached area. 
    */ 
    private Paint mReachedBarPaint; 
    /** 
    * the Painter of the unreached area. 
    */ 
    private Paint mUnreachedBarPaint; 
    /** 
    * the Painter of the progress text. 
    */ 
    private Paint mTextPaint; 

    /** 
    * Unreached Bar area to draw rect. 
    */ 
    private RectF mUnreachedRectF = new RectF(0,0,0,0); 
    /** 
    * reached bar area rect. 
    */ 
    private RectF mReachedRectF = new RectF(0,0,0,0); 

    /** 
    * the progress text offset. 
    */ 
    private float mOffset; 

    /** 
    * determine if need to draw unreached area 
    */ 
    private boolean mDrawUnreachedBar = true; 

    private boolean mDrawReachedBar = true; 

    private boolean mIfDrawText = true; 

    public enum ProgressTextVisibility{ 
     Visible,Invisible 
    }; 



    public NumberProgressBar(Context context) { 
     this(context, null); 
    } 

    public NumberProgressBar(Context context, AttributeSet attrs) { 
     this(context, attrs, R.attr.numberProgressBarStyle); 
    } 

    public NumberProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 

     mContext = context; 

     default_reached_bar_height = dp2px(1.5f); 
     default_unreached_bar_height = dp2px(1.0f); 
     default_text_size = sp2px(10); 
     default_progress_text_offset = dp2px(3.0f); 

     //load styled attributes. 
     final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.NumberProgressBar, 
       defStyleAttr, 0); 

     mReachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_reached_color, default_reached_color); 
     mUnreachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_unreached_color,default_unreached_color); 
     mTextColor = attributes.getColor(R.styleable.NumberProgressBar_progress_text_color,default_text_color); 
     mTextSize = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_size, default_text_size); 

     mReachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_reached_bar_height,default_reached_bar_height); 
     mUnreachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_unreached_bar_height,default_unreached_bar_height); 
     mOffset = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_offset,default_progress_text_offset); 

     int textVisible = attributes.getInt(R.styleable.NumberProgressBar_progress_text_visibility,PROGRESS_TEXT_VISIBLE); 
     if(textVisible != PROGRESS_TEXT_VISIBLE){ 
      mIfDrawText = false; 
     } 

     setProgress(attributes.getInt(R.styleable.NumberProgressBar_progress,0)); 
     setMax(attributes.getInt(R.styleable.NumberProgressBar_max, 100)); 
     // 
     attributes.recycle(); 

     initializePainters(); 

    } 

    @Override 
    protected int getSuggestedMinimumWidth() { 
     return (int)mTextSize; 
    } 

    @Override 
    protected int getSuggestedMinimumHeight() { 
     return Math.max((int)mTextSize,Math.max((int)mReachedBarHeight,(int)mUnreachedBarHeight)); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     setMeasuredDimension(measure(widthMeasureSpec,true), measure(heightMeasureSpec,false)); 
    } 

    private int measure(int measureSpec,boolean isWidth){ 
     int result; 
     int mode = MeasureSpec.getMode(measureSpec); 
     int size = MeasureSpec.getSize(measureSpec); 
     int padding = isWidth?getPaddingLeft()+getPaddingRight():getPaddingTop()+getPaddingBottom(); 
     if(mode == MeasureSpec.EXACTLY){ 
      result = size; 
     }else{ 
      result = isWidth ? getSuggestedMinimumWidth() : getSuggestedMinimumHeight(); 
      result += padding; 
      if(mode == MeasureSpec.AT_MOST){ 
       if(isWidth) { 
        result = Math.max(result, size); 
       } 
       else{ 
        result = Math.min(result, size); 
       } 
      } 
     } 
     return result; 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     if(mIfDrawText){ 
      calculateDrawRectF(); 
     }else{ 
      calculateDrawRectFWithoutProgressText(); 
     } 

     if(mDrawReachedBar){ 
      canvas.drawRect(mReachedRectF,mReachedBarPaint); 
     } 

     if(mDrawUnreachedBar) { 
      canvas.drawRect(mUnreachedRectF, mUnreachedBarPaint); 
     } 

     if(mIfDrawText) 
      canvas.drawText(mCurrentDrawText,mDrawTextStart,mDrawTextEnd,mTextPaint); 
    } 

    private void initializePainters(){ 
     mReachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
     mReachedBarPaint.setColor(mReachedBarColor); 

     mUnreachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
     mUnreachedBarPaint.setColor(mUnreachedBarColor); 

     mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
     mTextPaint.setColor(mTextColor); 
     mTextPaint.setTextSize(mTextSize); 
    } 


    private void calculateDrawRectFWithoutProgressText(){ 
     mReachedRectF.left = getPaddingLeft(); 
     mReachedRectF.top = getHeight()/2.0f - mReachedBarHeight/2.0f; 
     mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight())/(getMax()*1.0f) * getProgress() + getPaddingLeft(); 
     mReachedRectF.bottom = getHeight()/2.0f + mReachedBarHeight/2.0f; 

     mUnreachedRectF.left = mReachedRectF.right; 
     mUnreachedRectF.right = getWidth() - getPaddingRight(); 
     mUnreachedRectF.top = getHeight()/2.0f + - mUnreachedBarHeight/2.0f; 
     mUnreachedRectF.bottom = getHeight()/2.0f + mUnreachedBarHeight/2.0f; 
    } 

    private void calculateDrawRectF(){ 

     mCurrentDrawText = String.format("%d" ,getProgress()*100/getMax()); 
     mCurrentDrawText = mPrefix + mCurrentDrawText + mSuffix; 
     mDrawTextWidth = mTextPaint.measureText(mCurrentDrawText); 

     if(getProgress() == 0){ 
      mDrawReachedBar = false; 
      mDrawTextStart = getPaddingLeft(); 
     }else{ 
      mDrawReachedBar = true; 
      mReachedRectF.left = getPaddingLeft(); 
      mReachedRectF.top = getHeight()/2.0f - mReachedBarHeight/2.0f; 
      mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight())/(getMax()*1.0f) * getProgress() - mOffset + getPaddingLeft(); 
      mReachedRectF.bottom = getHeight()/2.0f + mReachedBarHeight/2.0f; 
      mDrawTextStart = (mReachedRectF.right + mOffset); 
     } 

     mDrawTextEnd = (int) ((getHeight()/2.0f) - ((mTextPaint.descent() + mTextPaint.ascent())/2.0f)) ; 

     if((mDrawTextStart + mDrawTextWidth)>= getWidth() - getPaddingRight()){ 
      mDrawTextStart = getWidth() - getPaddingRight() - mDrawTextWidth; 
      mReachedRectF.right = mDrawTextStart - mOffset; 
     } 

     float unreachedBarStart = mDrawTextStart + mDrawTextWidth + mOffset; 
     if(unreachedBarStart >= getWidth() - getPaddingRight()){ 
      mDrawUnreachedBar = false; 
     }else{ 
      mDrawUnreachedBar = true; 
      mUnreachedRectF.left = unreachedBarStart; 
      mUnreachedRectF.right = getWidth() - getPaddingRight(); 
      mUnreachedRectF.top = getHeight()/2.0f + - mUnreachedBarHeight/2.0f; 
      mUnreachedRectF.bottom = getHeight()/2.0f + mUnreachedBarHeight/2.0f; 
     } 
    } 
    /** 
    * get progress text color 
    * @return progress text color 
    */ 
    public int getTextColor() { 
     return mTextColor; 
    } 

    /** 
    * get progress text size 
    * @return progress text size 
    */ 
    public float getProgressTextSize() { 
     return mTextSize; 
    } 

    public int getUnreachedBarColor() { 
     return mUnreachedBarColor; 
    } 

    public int getReachedBarColor() { 
     return mReachedBarColor; 
    } 

    public int getProgress() { 
     return mProgress; 
    } 

    public int getMax() { 
     return mMax; 
    } 

    public float getReachedBarHeight(){ 
     return mReachedBarHeight; 
    } 

    public float getUnreachedBarHeight(){ 
     return mUnreachedBarHeight; 
    } 

    public void setProgressTextSize(float TextSize) { 
     this.mTextSize = TextSize; 
     mTextPaint.setTextSize(mTextSize); 
     invalidate(); 
    } 

    public void setProgressTextColor(int TextColor) { 
     this.mTextColor = TextColor; 
     mTextPaint.setColor(mTextColor); 
     invalidate(); 
    } 

    public void setUnreachedBarColor(int BarColor) { 
     this.mUnreachedBarColor = BarColor; 
     mUnreachedBarPaint.setColor(mReachedBarColor); 
     invalidate(); 
    } 

    public void setReachedBarColor(int ProgressColor) { 
     this.mReachedBarColor = ProgressColor; 
     mReachedBarPaint.setColor(mReachedBarColor); 
     invalidate(); 
    } 

    public void setReachedBarHeight(float height){ 
     mReachedBarHeight = height; 
    } 

    public void setUnreachedBarHeight(float height){ 
     mUnreachedBarHeight = height; 
    } 

    public void setMax(int Max) { 
     if(Max > 0){ 
      this.mMax = Max; 
      invalidate(); 
     } 
    } 

    public void setSuffix(String suffix){ 
     if(suffix == null){ 
      mSuffix = ""; 
     }else{ 
      mSuffix = suffix; 
     } 
    } 

    public String getSuffix(){ 
     return mSuffix; 
    } 

    public void setPrefix(String prefix){ 
     if(prefix == null) 
      mPrefix = ""; 
     else{ 
      mPrefix = prefix; 
     } 
    } 

    public String getPrefix(){ 
     return mPrefix; 
    } 

    public void incrementProgressBy(int by){ 
     if(by > 0){ 
      setProgress(getProgress() + by); 
     } 
    } 

    public void setProgress(int Progress) { 
     if(Progress <= getMax() && Progress >= 0){ 
      this.mProgress = Progress; 
      invalidate(); 
     } 
    } 

    @Override 
    protected Parcelable onSaveInstanceState() { 
     final Bundle bundle = new Bundle(); 
     bundle.putParcelable(INSTANCE_STATE,super.onSaveInstanceState()); 
     bundle.putInt(INSTANCE_TEXT_COLOR,getTextColor()); 
     bundle.putFloat(INSTANCE_TEXT_SIZE, getProgressTextSize()); 
     bundle.putFloat(INSTANCE_REACHED_BAR_HEIGHT,getReachedBarHeight()); 
     bundle.putFloat(INSTANCE_UNREACHED_BAR_HEIGHT,getUnreachedBarHeight()); 
     bundle.putInt(INSTANCE_REACHED_BAR_COLOR,getReachedBarColor()); 
     bundle.putInt(INSTANCE_UNREACHED_BAR_COLOR,getUnreachedBarColor()); 
     bundle.putInt(INSTANCE_MAX,getMax()); 
     bundle.putInt(INSTANCE_PROGRESS,getProgress()); 
     bundle.putString(INSTANCE_SUFFIX,getSuffix()); 
     bundle.putString(INSTANCE_PREFIX,getPrefix()); 
     bundle.putBoolean(INSTANCE_TEXT_VISBILITY, getProgressTextVisibility()); 
     return bundle; 
    } 

    @Override 
    protected void onRestoreInstanceState(Parcelable state) { 
     if(state instanceof Bundle){ 
      final Bundle bundle = (Bundle)state; 
      mTextColor = bundle.getInt(INSTANCE_TEXT_COLOR); 
      mTextSize = bundle.getFloat(INSTANCE_TEXT_SIZE); 
      mReachedBarHeight = bundle.getFloat(INSTANCE_REACHED_BAR_HEIGHT); 
      mUnreachedBarHeight = bundle.getFloat(INSTANCE_UNREACHED_BAR_HEIGHT); 
      mReachedBarColor = bundle.getInt(INSTANCE_REACHED_BAR_COLOR); 
      mUnreachedBarColor = bundle.getInt(INSTANCE_UNREACHED_BAR_COLOR); 
      initializePainters(); 
      setMax(bundle.getInt(INSTANCE_MAX)); 
      setProgress(bundle.getInt(INSTANCE_PROGRESS)); 
      setPrefix(bundle.getString(INSTANCE_PREFIX)); 
      setSuffix(bundle.getString(INSTANCE_SUFFIX)); 
      setProgressTextVisibility(bundle.getBoolean(INSTANCE_TEXT_VISBILITY) ? ProgressTextVisibility.Visible : ProgressTextVisibility.Invisible); 
      super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE)); 
      return; 
     } 
     super.onRestoreInstanceState(state); 
    } 

    public float dp2px(float dp) { 
     final float scale = getResources().getDisplayMetrics().density; 
     return dp * scale + 0.5f; 
    } 

    public float sp2px(float sp){ 
     final float scale = getResources().getDisplayMetrics().scaledDensity; 
     return sp * scale; 
    } 

    public void setProgressTextVisibility(ProgressTextVisibility visibility){ 
     mIfDrawText = visibility == ProgressTextVisibility.Visible; 
     invalidate(); 
    } 

    public boolean getProgressTextVisibility() { 
     return mIfDrawText; 
    } 

} 

Link 1

Link 2

Link 3

Link 4

Link 5

Link 6

Si può anche farlo con il layout lineare. Ho fatto un semplice esempio, solo un semplice esempio.

<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" > 

    <LinearLayout 
     android:id="@+id/ll_progress" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerHorizontal="true" 
     android:background="@drawable/layout" > 

     <ImageView 
      android:id="@+id/ImageView01" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_marginLeft="10dp" 
      android:layout_marginTop="14dp" 
      android:src="@drawable/bg_1" /> 

     <ImageView 
      android:id="@+id/imageView1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_marginLeft="38dp" 
      android:layout_marginTop="14dp" 
      android:src="@drawable/bg_1" /> 


     <ImageView 
      android:id="@+id/imageView12" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_marginLeft="35dp" 
      android:layout_marginTop="14dp" 
      android:src="@drawable/bg_1" /> 

    </LinearLayout> 

</RelativeLayout> 

bg_1 bg layout

MainActivity.java

import java.util.concurrent.TimeUnit; 

import android.app.Activity; 
import android.graphics.BitmapFactory; 
import android.graphics.drawable.BitmapDrawable; 
import android.graphics.drawable.Drawable; 
import android.graphics.drawable.TransitionDrawable; 
import android.os.Bundle; 
import android.os.Handler; 
import android.widget.ImageView; 
import android.widget.LinearLayout; 

public class MainActivity extends Activity { 

    LinearLayout llProgress; 
    Handler handler; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     llProgress = (LinearLayout) findViewById(R.id.ll_progress); 
     handler = new Handler(getMainLooper()); 

     startTransition(); 
    } 

    int prevChild = 0; 

    private void startTransition() { 
     // create the transition layers 
     Drawable[] layers = new Drawable[2]; 
     layers[0] = new BitmapDrawable(getResources(), BitmapFactory.decodeResource(getResources(), R.drawable.bg)); 
     layers[1] = new BitmapDrawable(getResources(), BitmapFactory.decodeResource(getResources(), R.drawable.bg_1)); 

     final TransitionDrawable[] transitionDrawable = new TransitionDrawable[llProgress.getChildCount()]; 
     for (int i = 0; i < llProgress.getChildCount(); i++) { 
      transitionDrawable[i] = new TransitionDrawable(layers); 
      ((ImageView) llProgress.getChildAt(i)).setImageDrawable(transitionDrawable[i]); 
     } 

     handler.postDelayed(new Runnable() { 

      @Override 
      public void run() { 
       transitionDrawable[prevChild++].startTransition(1000); 
       if(prevChild > llProgress.getChildCount() - 1){ 
        prevChild = 0; 
       } 
       handler.postDelayed(this, 1000 * 3); 
      } 
     }, 1000 * 3); 

    } 

1 2

-1

Il widget ProgressBar delegati il ​​disegno del suo progresso ad esso è assegnato il progresso Drawable impostando il livello appropriato su di esso. L'avanzamento predefinito *Drawable è un layer-list** che contiene tre livelli: sfondo, avanzamento e avanzamento secondario. Gli ultimi due sono avvolti nei contenitori clip o scale che vengono automaticamente ritagliati o ridimensionati in base alla loro percentuale in base ai loro livelli. Sono inoltre stati assegnati ID speciali a ProgressBar ricerche e gestiti specificatamente anziché all'intero Drawable se lo Drawable risulta essere un layer-list.

Nel tuo caso, poiché gli incrementi di avanzamento non sono tutti uguali, puoi utilizzare un contenitore disegnabile level-list come livello di avanzamento e fornire risorse per tutti gli incrementi di avanzamento. In alternativa, se desideri renderlo dinamico, puoi creare una sottoclasse personalizzata con Drawable con la logica di disegno appropriata in base al suo livello.

Ecco un XML di esempio per la risorsa di avanzamento Drawable utilizzando un level-list:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:id="@android:id/background" 
      android:drawable="@drawable/progress_bg" /> 
    <item android:id="@android:id/progress"> 
     <level-list> 
      <item android:drawable="@android:color/transparent" /> 
      <item android:drawable="@drawable/progress_1" /> 
      <item android:drawable="@drawable/progress_2" /> 
      <item android:drawable="@drawable/progress_3" /> 
     </level-list> 
    </item> 
</layer-list> 


* È possibile trovare l'originale non-Holo versione here, e le versioni Holo here e here.
** È possibile trovare un elenco del framework standard Drawable s che può essere definito in XML here.