加载网络图片所显示的转圈效果及加载成功前与失败后所显示的图标

来源:互联网 发布:fc游戏制作软件 编辑:程序博客网 时间:2024/05/01 02:57


MainActivity的一个调用方法:

    //网络图片下载    private void downLoadFile(final String url, final String target, final String fileName) {        //设置成临时文件后缀名        final String fileTempName = FileUtils.getFileTempName(target);        HttpUtils http = XUtilsHttpClient.getInstanceManageToFile(MainActivity.this);        http.download(url, fileTempName,                true, // 如果目标文件存在,接着未完成的部分继续下载。服务器不支持RANGE时将从新下载。                true, // 如果从请求返回信息中获取到文件名,下载完成后自动重命名。                new RequestCallBack<File>() {                    @Override                    public void onStart() {                        progressWheel.spin();//开始时调用的是加载圆圈方法显示                        progress_wheel_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.ic_image_loading_default));//这里是调用开始下载时的图片                    }                    @Override                    public void onLoading(long total, long current, boolean isUploading) {                    }                    @Override                    public void onSuccess(ResponseInfo<File> responseInfo) {                        progressWheel.stopSpinning();                        String filePathName = FileUtils.reductionFileName(fileTempName, fileName);                        System.out.println(".............filePathName = " + filePathName);                        showImage(filePathName);                    @Override                    public void onFailure(HttpException error, String msg) {                        Log.e("................", "onFailure: ", error);                        progressWheel.stopSpinning();                        Toast.makeText(MainActivity.this.this, "动态图加载失败...", Toast.LENGTH_SHORT).show();                        progress_wheel_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.ic_image_loading_failed));//这里是调用下载失败后的图片                    }                });    }

activity_main:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"              android:orientation="vertical"              android:layout_width="match_parent"              android:layout_height="match_parent">    <RelativeLayout            android:layout_width="match_parent"            android:layout_height="match_parent">        <RelativeLayout                android:id="@+id/progress_wheel_layout"                android:layout_centerVertical="true"                android:layout_centerHorizontal="true"                android:background="@color/black"                android:layout_width="250dp"                android:layout_height="250dp">            <com.pnikosis.materialishprogress.ProgressWheel                    android:id="@+id/progress_wheel"                    android:layout_width="80dp"                    android:layout_height="80dp"                    android:layout_centerHorizontal="true"                    android:layout_centerVertical="true"                    wheel:matProg_barColor="#5588FF"                    wheel:matProg_progressIndeterminate="true"/>        </RelativeLayout>        <!--所要显示的网络图片-->        <ImageView                android:id="@+id/image_view"                android:layout_centerInParent="true"                android:layout_width="fill_parent"                android:layout_height="fill_parent"                />    </RelativeLayout></LinearLayout>

这是自定义的一个类:

package com.pnikosis.materialishprogress;import android.annotation.TargetApi;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.RectF;import android.os.Build;import android.os.Parcel;import android.os.Parcelable;import android.os.SystemClock;import android.provider.Settings;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.TypedValue;import android.view.View;/** * A Material style progress wheel, compatible up to 2.2. * Todd Davies' Progress Wheel https://github.com/Todd-Davies/ProgressWheel * * @author Nico Hormazábal *         <p/> *         Licensed under the Apache License 2.0 license see: *         http://www.apache.org/licenses/LICENSE-2.0 */public class ProgressWheel extends View {  private static final String TAG = ProgressWheel.class.getSimpleName();  private final int barLength = 16;  private final int barMaxLength = 270;  private final long pauseGrowingTime = 200;  /**   * *********   * DEFAULTS *   * **********   */  //Sizes (with defaults in DP)  private int circleRadius = 28;  private int barWidth = 4;  private int rimWidth = 4;  private boolean fillRadius = false;  private double timeStartGrowing = 0;  private double barSpinCycleTime = 460;  private float barExtraLength = 0;  private boolean barGrowingFromFront = true;  private long pausedTimeWithoutGrowing = 0;  //Colors (with defaults)  private int barColor = 0xAA000000;  private int rimColor = 0x00FFFFFF;  //Paints  private Paint barPaint = new Paint();  private Paint rimPaint = new Paint();  //Rectangles  private RectF circleBounds = new RectF();  //Animation  //The amount of degrees per second  private float spinSpeed = 230.0f;  //private float spinSpeed = 120.0f;  // The last time the spinner was animated  private long lastTimeAnimated = 0;  private boolean linearProgress;  private float mProgress = 0.0f;  private float mTargetProgress = 0.0f;  private boolean isSpinning = false;  private ProgressCallback callback;  private boolean shouldAnimate;  /**   * The constructor for the ProgressWheel   */  public ProgressWheel(Context context, AttributeSet attrs) {    super(context, attrs);    parseAttributes(context.obtainStyledAttributes(attrs, R.styleable.ProgressWheel));    setAnimationEnabled();  }  /**   * The constructor for the ProgressWheel   */  public ProgressWheel(Context context) {    super(context);    setAnimationEnabled();  }  @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) private void setAnimationEnabled() {    int currentApiVersion = android.os.Build.VERSION.SDK_INT;    float animationValue;    if (currentApiVersion >= Build.VERSION_CODES.JELLY_BEAN_MR1) {      animationValue = Settings.Global.getFloat(getContext().getContentResolver(),          Settings.Global.ANIMATOR_DURATION_SCALE, 1);    } else {      animationValue = Settings.System.getFloat(getContext().getContentResolver(),          Settings.System.ANIMATOR_DURATION_SCALE, 1);    }    shouldAnimate = animationValue != 0;  }  //----------------------------------  //Setting up stuff  //----------------------------------  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    int viewWidth = circleRadius + this.getPaddingLeft() + this.getPaddingRight();    int viewHeight = circleRadius + this.getPaddingTop() + this.getPaddingBottom();    int widthMode = MeasureSpec.getMode(widthMeasureSpec);    int widthSize = MeasureSpec.getSize(widthMeasureSpec);    int heightMode = MeasureSpec.getMode(heightMeasureSpec);    int heightSize = MeasureSpec.getSize(heightMeasureSpec);    int width;    int height;    //Measure Width    if (widthMode == MeasureSpec.EXACTLY) {      //Must be this size      width = widthSize;    } else if (widthMode == MeasureSpec.AT_MOST) {      //Can't be bigger than...      width = Math.min(viewWidth, widthSize);    } else {      //Be whatever you want      width = viewWidth;    }    //Measure Height    if (heightMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.EXACTLY) {      //Must be this size      height = heightSize;    } else if (heightMode == MeasureSpec.AT_MOST) {      //Can't be bigger than...      height = Math.min(viewHeight, heightSize);    } else {      //Be whatever you want      height = viewHeight;    }    setMeasuredDimension(width, height);  }  /**   * Use onSizeChanged instead of onAttachedToWindow to get the dimensions of the view,   * because this method is called after measuring the dimensions of MATCH_PARENT & WRAP_CONTENT.   * Use this dimensions to setup the bounds and paints.   */  @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {    super.onSizeChanged(w, h, oldw, oldh);    setupBounds(w, h);    setupPaints();    invalidate();  }  /**   * Set the properties of the paints we're using to   * draw the progress wheel   */  private void setupPaints() {    barPaint.setColor(barColor);    barPaint.setAntiAlias(true);    barPaint.setStyle(Style.STROKE);    barPaint.setStrokeWidth(barWidth);    rimPaint.setColor(rimColor);    rimPaint.setAntiAlias(true);    rimPaint.setStyle(Style.STROKE);    rimPaint.setStrokeWidth(rimWidth);  }  /**   * Set the bounds of the component   */  private void setupBounds(int layout_width, int layout_height) {    int paddingTop = getPaddingTop();    int paddingBottom = getPaddingBottom();    int paddingLeft = getPaddingLeft();    int paddingRight = getPaddingRight();    if (!fillRadius) {      // Width should equal to Height, find the min value to setup the circle      int minValue = Math.min(layout_width - paddingLeft - paddingRight,          layout_height - paddingBottom - paddingTop);      int circleDiameter = Math.min(minValue, circleRadius * 2 - barWidth * 2);      // Calc the Offset if needed for centering the wheel in the available space      int xOffset = (layout_width - paddingLeft - paddingRight - circleDiameter) / 2 + paddingLeft;      int yOffset = (layout_height - paddingTop - paddingBottom - circleDiameter) / 2 + paddingTop;      circleBounds =          new RectF(xOffset + barWidth, yOffset + barWidth, xOffset + circleDiameter - barWidth,              yOffset + circleDiameter - barWidth);    } else {      circleBounds = new RectF(paddingLeft + barWidth, paddingTop + barWidth,          layout_width - paddingRight - barWidth, layout_height - paddingBottom - barWidth);    }  }  /**   * Parse the attributes passed to the view from the XML   *   * @param a the attributes to parse   */  private void parseAttributes(TypedArray a) {    // We transform the default values from DIP to pixels    DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();    barWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, barWidth, metrics);    rimWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rimWidth, metrics);    circleRadius =        (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, circleRadius, metrics);    circleRadius =        (int) a.getDimension(R.styleable.ProgressWheel_matProg_circleRadius, circleRadius);    fillRadius = a.getBoolean(R.styleable.ProgressWheel_matProg_fillRadius, false);    barWidth = (int) a.getDimension(R.styleable.ProgressWheel_matProg_barWidth, barWidth);    rimWidth = (int) a.getDimension(R.styleable.ProgressWheel_matProg_rimWidth, rimWidth);    float baseSpinSpeed =        a.getFloat(R.styleable.ProgressWheel_matProg_spinSpeed, spinSpeed / 360.0f);    spinSpeed = baseSpinSpeed * 360;    barSpinCycleTime =        a.getInt(R.styleable.ProgressWheel_matProg_barSpinCycleTime, (int) barSpinCycleTime);    barColor = a.getColor(R.styleable.ProgressWheel_matProg_barColor, barColor);    rimColor = a.getColor(R.styleable.ProgressWheel_matProg_rimColor, rimColor);    linearProgress = a.getBoolean(R.styleable.ProgressWheel_matProg_linearProgress, false);    if (a.getBoolean(R.styleable.ProgressWheel_matProg_progressIndeterminate, false)) {      spin();    }    // Recycle    a.recycle();  }  public void setCallback(ProgressCallback progressCallback) {    callback = progressCallback;    if (!isSpinning) {      runCallback();    }  }  //----------------------------------  //Animation stuff  //----------------------------------  @TargetApi(Build.VERSION_CODES.CUPCAKE)  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    canvas.drawArc(circleBounds, 360, 360, false, rimPaint);    boolean mustInvalidate = false;    if (!shouldAnimate) {      return;    }    if (isSpinning) {      //Draw the spinning bar      mustInvalidate = true;      long deltaTime = (SystemClock.uptimeMillis() - lastTimeAnimated);      float deltaNormalized = deltaTime * spinSpeed / 1000.0f;      updateBarLength(deltaTime);      mProgress += deltaNormalized;      if (mProgress > 360) {        mProgress -= 360f;        // A full turn has been completed        // we run the callback with -1 in case we want to        // do something, like changing the color        runCallback(-1.0f);      }      lastTimeAnimated = SystemClock.uptimeMillis();      float from = mProgress - 90;      float length = barLength + barExtraLength;      if (isInEditMode()) {        from = 0;        length = 135;      }      canvas.drawArc(circleBounds, from, length, false, barPaint);    } else {      float oldProgress = mProgress;      if (mProgress != mTargetProgress) {        //We smoothly increase the progress bar        mustInvalidate = true;        float deltaTime = (float) (SystemClock.uptimeMillis() - lastTimeAnimated) / 1000;        float deltaNormalized = deltaTime * spinSpeed;        mProgress = Math.min(mProgress + deltaNormalized, mTargetProgress);        lastTimeAnimated = SystemClock.uptimeMillis();      }      if (oldProgress != mProgress) {        runCallback();      }      float offset = 0.0f;      float progress = mProgress;      if (!linearProgress) {        float factor = 2.0f;        offset = (float) (1.0f - Math.pow(1.0f - mProgress / 360.0f, 2.0f * factor)) * 360.0f;        progress = (float) (1.0f - Math.pow(1.0f - mProgress / 360.0f, factor)) * 360.0f;      }      if (isInEditMode()) {        progress = 360;      }      canvas.drawArc(circleBounds, offset - 90, progress, false, barPaint);    }    if (mustInvalidate) {      invalidate();    }  }  @Override protected void onVisibilityChanged(View changedView, int visibility) {    super.onVisibilityChanged(changedView, visibility);    if (visibility == VISIBLE) {      lastTimeAnimated = SystemClock.uptimeMillis();    }  }  private void updateBarLength(long deltaTimeInMilliSeconds) {    if (pausedTimeWithoutGrowing >= pauseGrowingTime) {      timeStartGrowing += deltaTimeInMilliSeconds;      if (timeStartGrowing > barSpinCycleTime) {        // We completed a size change cycle        // (growing or shrinking)        timeStartGrowing -= barSpinCycleTime;        //if(barGrowingFromFront) {        pausedTimeWithoutGrowing = 0;        //}        barGrowingFromFront = !barGrowingFromFront;      }      float distance =          (float) Math.cos((timeStartGrowing / barSpinCycleTime + 1) * Math.PI) / 2 + 0.5f;      float destLength = (barMaxLength - barLength);      if (barGrowingFromFront) {        barExtraLength = distance * destLength;      } else {        float newLength = destLength * (1 - distance);        mProgress += (barExtraLength - newLength);        barExtraLength = newLength;      }    } else {      pausedTimeWithoutGrowing += deltaTimeInMilliSeconds;    }  }  /**   * Check if the wheel is currently spinning   */  public boolean isSpinning() {    return isSpinning;  }  /**   * Reset the count (in increment mode)   */  public void resetCount() {    mProgress = 0.0f;    mTargetProgress = 0.0f;    invalidate();  }  /**   * Turn off spin mode   */  public void stopSpinning() {    isSpinning = false;    mProgress = 0.0f;    mTargetProgress = 0.0f;    invalidate();  }  /**   * Puts the view on spin mode   */  public void spin() {    lastTimeAnimated = SystemClock.uptimeMillis();    isSpinning = true;    invalidate();  }  private void runCallback(float value) {    if (callback != null) {      callback.onProgressUpdate(value);    }  }  private void runCallback() {    if (callback != null) {      float normalizedProgress = (float) Math.round(mProgress * 100 / 360.0f) / 100;      callback.onProgressUpdate(normalizedProgress);    }  }  /**   * Set the progress to a specific value,   * the bar will be set instantly to that value   *   * @param progress the progress between 0 and 1   */  public void setInstantProgress(float progress) {    if (isSpinning) {      mProgress = 0.0f;      isSpinning = false;    }    if (progress > 1.0f) {      progress -= 1.0f;    } else if (progress < 0) {      progress = 0;    }    if (progress == mTargetProgress) {      return;    }    mTargetProgress = Math.min(progress * 360.0f, 360.0f);    mProgress = mTargetProgress;    lastTimeAnimated = SystemClock.uptimeMillis();    invalidate();  }  // Great way to save a view's state http://stackoverflow.com/a/7089687/1991053  @Override public Parcelable onSaveInstanceState() {    Parcelable superState = super.onSaveInstanceState();    WheelSavedState ss = new WheelSavedState(superState);    // We save everything that can be changed at runtime    ss.mProgress = this.mProgress;    ss.mTargetProgress = this.mTargetProgress;    ss.isSpinning = this.isSpinning;    ss.spinSpeed = this.spinSpeed;    ss.barWidth = this.barWidth;    ss.barColor = this.barColor;    ss.rimWidth = this.rimWidth;    ss.rimColor = this.rimColor;    ss.circleRadius = this.circleRadius;    ss.linearProgress = this.linearProgress;    ss.fillRadius = this.fillRadius;    return ss;  }  @Override public void onRestoreInstanceState(Parcelable state) {    if (!(state instanceof WheelSavedState)) {      super.onRestoreInstanceState(state);      return;    }    WheelSavedState ss = (WheelSavedState) state;    super.onRestoreInstanceState(ss.getSuperState());    this.mProgress = ss.mProgress;    this.mTargetProgress = ss.mTargetProgress;    this.isSpinning = ss.isSpinning;    this.spinSpeed = ss.spinSpeed;    this.barWidth = ss.barWidth;    this.barColor = ss.barColor;    this.rimWidth = ss.rimWidth;    this.rimColor = ss.rimColor;    this.circleRadius = ss.circleRadius;    this.linearProgress = ss.linearProgress;    this.fillRadius = ss.fillRadius;    this.lastTimeAnimated = SystemClock.uptimeMillis();  }  /**   * @return the current progress between 0.0 and 1.0,   * if the wheel is indeterminate, then the result is -1   */  public float getProgress() {    return isSpinning ? -1 : mProgress / 360.0f;  }  //----------------------------------  //Getters + setters  //----------------------------------  /**   * Set the progress to a specific value,   * the bar will smoothly animate until that value   *   * @param progress the progress between 0 and 1   */  public void setProgress(float progress) {    if (isSpinning) {      mProgress = 0.0f;      isSpinning = false;      runCallback();    }    if (progress > 1.0f) {      progress -= 1.0f;    } else if (progress < 0) {      progress = 0;    }    if (progress == mTargetProgress) {      return;    }    // If we are currently in the right position    // we set again the last time animated so the    // animation starts smooth from here    if (mProgress == mTargetProgress) {      lastTimeAnimated = SystemClock.uptimeMillis();    }    mTargetProgress = Math.min(progress * 360.0f, 360.0f);    invalidate();  }  /**   * Sets the determinate progress mode   *   * @param isLinear if the progress should increase linearly   */  public void setLinearProgress(boolean isLinear) {    linearProgress = isLinear;    if (!isSpinning) {      invalidate();    }  }  /**   * @return the radius of the wheel in pixels   */  public int getCircleRadius() {    return circleRadius;  }  /**   * Sets the radius of the wheel   *   * @param circleRadius the expected radius, in pixels   */  public void setCircleRadius(int circleRadius) {    this.circleRadius = circleRadius;    if (!isSpinning) {      invalidate();    }  }  /**   * @return the width of the spinning bar   */  public int getBarWidth() {    return barWidth;  }  /**   * Sets the width of the spinning bar   *   * @param barWidth the spinning bar width in pixels   */  public void setBarWidth(int barWidth) {    this.barWidth = barWidth;    if (!isSpinning) {      invalidate();    }  }  /**   * @return the color of the spinning bar   */  public int getBarColor() {    return barColor;  }  /**   * Sets the color of the spinning bar   *   * @param barColor The spinning bar color   */  public void setBarColor(int barColor) {    this.barColor = barColor;    setupPaints();    if (!isSpinning) {      invalidate();    }  }  /**   * @return the color of the wheel's contour   */  public int getRimColor() {    return rimColor;  }  /**   * Sets the color of the wheel's contour   *   * @param rimColor the color for the wheel   */  public void setRimColor(int rimColor) {    this.rimColor = rimColor;    setupPaints();    if (!isSpinning) {      invalidate();    }  }  /**   * @return the base spinning speed, in full circle turns per second   * (1.0 equals on full turn in one second), this value also is applied for   * the smoothness when setting a progress   */  public float getSpinSpeed() {    return spinSpeed / 360.0f;  }  /**   * Sets the base spinning speed, in full circle turns per second   * (1.0 equals on full turn in one second), this value also is applied for   * the smoothness when setting a progress   *   * @param spinSpeed the desired base speed in full turns per second   */  public void setSpinSpeed(float spinSpeed) {    this.spinSpeed = spinSpeed * 360.0f;  }  /**   * @return the width of the wheel's contour in pixels   */  public int getRimWidth() {    return rimWidth;  }  /**   * Sets the width of the wheel's contour   *   * @param rimWidth the width in pixels   */  public void setRimWidth(int rimWidth) {    this.rimWidth = rimWidth;    if (!isSpinning) {      invalidate();    }  }  public interface ProgressCallback {    /**     * Method to call when the progress reaches a value     * in order to avoid float precision issues, the progress     * is rounded to a float with two decimals.     *     * In indeterminate mode, the callback is called each time     * the wheel completes an animation cycle, with, the progress value is -1.0f     *     * @param progress a double value between 0.00 and 1.00 both included     */    public void onProgressUpdate(float progress);  }  static class WheelSavedState extends BaseSavedState {    //required field that makes Parcelables from a Parcel    public static final Parcelable.Creator<WheelSavedState> CREATOR =        new Parcelable.Creator<WheelSavedState>() {          public WheelSavedState createFromParcel(Parcel in) {            return new WheelSavedState(in);          }          public WheelSavedState[] newArray(int size) {            return new WheelSavedState[size];          }        };    float mProgress;    float mTargetProgress;    boolean isSpinning;    float spinSpeed;    int barWidth;    int barColor;    int rimWidth;    int rimColor;    int circleRadius;    boolean linearProgress;    boolean fillRadius;    WheelSavedState(Parcelable superState) {      super(superState);    }    private WheelSavedState(Parcel in) {      super(in);      this.mProgress = in.readFloat();      this.mTargetProgress = in.readFloat();      this.isSpinning = in.readByte() != 0;      this.spinSpeed = in.readFloat();      this.barWidth = in.readInt();      this.barColor = in.readInt();      this.rimWidth = in.readInt();      this.rimColor = in.readInt();      this.circleRadius = in.readInt();      this.linearProgress = in.readByte() != 0;      this.fillRadius = in.readByte() != 0;    }    @Override public void writeToParcel(Parcel out, int flags) {      super.writeToParcel(out, flags);      out.writeFloat(this.mProgress);      out.writeFloat(this.mTargetProgress);      out.writeByte((byte) (isSpinning ? 1 : 0));      out.writeFloat(this.spinSpeed);      out.writeInt(this.barWidth);      out.writeInt(this.barColor);      out.writeInt(this.rimWidth);      out.writeInt(this.rimColor);      out.writeInt(this.circleRadius);      out.writeByte((byte) (linearProgress ? 1 : 0));      out.writeByte((byte) (fillRadius ? 1 : 0));    }  }}
这是搭好布局的截图:


如果我们需要加载网络图片时,首先开始加载图片时会显示一个刚开始类似图片的背景图和加载的圈圈效果。

如果加载失败则在失败那里加载圆圈失败后显示一个失败的图出来。

这里Relativelayout中的id为progress_wheel_layout这个布局就是我们设置在加载圆圈时的背景图。

下图为加载失败时的截图显示:




0 0