Custom Drawable for ProgressBar/ProgressDialog

2018-12-31 12:34发布

问题:

Reading the limited documentation that Google has provided, I get the feeling that it is possible to change the look (drawable) of a ProgressBar/ProgressDialog by simply creating a new style an assigning it to the style property of the ProgressBar. But I cannot get this to work properly. Here is what I did so far:

I created a shape like this (mp2.xml)

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"
  android:shape=\"ring\"
  android:innerRadiusRatio=\"4\"
  android:thicknessRatio=\"4\"
  android:useLevel=\"false\">
 <size android:width=\"50dip\" android:height=\"50dip\" />
 <gradient android:type=\"sweep\" android:useLevel=\"false\" android:startColor=\"#300000ff\" android:centerColor=\"#500000ff\" android:endColor=\"#ff0000ff\" />
</shape>

then created an animation (mp3.xml) like this:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<animation-list xmlns:android=\"http://schemas.android.com/apk/res/android\" android:oneshot=\"false\">
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"0\" android:toDegrees=\"30\" android:repeatCount=\"1\" />
 </item>
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"30\" android:toDegrees=\"60\" android:repeatCount=\"1\" />
 </item>
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"60\" android:toDegrees=\"90\" android:repeatCount=\"1\" />
 </item>
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"90\" android:toDegrees=\"120\" android:repeatCount=\"1\" />
 </item>
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"120\" android:toDegrees=\"150\" android:repeatCount=\"1\" />
 </item>
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"150\" android:toDegrees=\"180\" android:repeatCount=\"1\" />
 </item>
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"180\" android:toDegrees=\"210\" android:repeatCount=\"1\" />
 </item>
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"210\" android:toDegrees=\"240\" android:repeatCount=\"1\" />
 </item>
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"240\" android:toDegrees=\"270\" android:repeatCount=\"1\" />
 </item>
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"270\" android:toDegrees=\"300\" android:repeatCount=\"1\" />
 </item>
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"300\" android:toDegrees=\"330\" android:repeatCount=\"1\" />
 </item>
 <item android:duration=\"70\">
  <rotate xmlns:android=\"http://schemas.android.com/apk/res/android\" android:drawable=\"@drawable/mp2\" android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"330\" android:toDegrees=\"360\" android:repeatCount=\"1\" />
 </item>
</animation-list>

then created a style (attrs.xml) like this:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<resources>
 <style parent=\"@android:style/Widget.ProgressBar\" name=\"customProgressBar\">
  <item name=\"android:progressDrawable\">@anim/mp3</item>
 </style>
</resources>

and the in my main.xml I have set the style like this:

<?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\" android:drawingCacheQuality=\"high\">
 <ProgressBar android:id=\"@+id/ProgressBar01\"
     android:layout_width=\"wrap_content\"
     android:layout_height=\"wrap_content\" style=\"@style/customProgressBar\"/>
</LinearLayout>

But it still shows the same drawable as before. What am I doing wrong?

回答1:

I used the following for creating a custom progress bar.

File res/drawable/progress_bar_states.xml declares the colors of the different states:

<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">

    <item android:id=\"@android:id/background\">
        <shape>
            <gradient
                    android:startColor=\"#000001\"
                    android:centerColor=\"#0b131e\"
                    android:centerY=\"0.75\"
                    android:endColor=\"#0d1522\"
                    android:angle=\"270\"
            />
        </shape>
    </item>

    <item android:id=\"@android:id/secondaryProgress\">
        <clip>
            <shape>
                <gradient
                        android:startColor=\"#234\"
                        android:centerColor=\"#234\"
                        android:centerY=\"0.75\"
                        android:endColor=\"#a24\"
                        android:angle=\"270\"
                />
            </shape>
        </clip>
    </item>

    <item android:id=\"@android:id/progress\">
        <clip>
            <shape>
                <gradient
                    android:startColor=\"#144281\"
                    android:centerColor=\"#0b1f3c\"
                    android:centerY=\"0.75\"
                    android:endColor=\"#06101d\"
                    android:angle=\"270\"
                />
            </shape>
        </clip>
    </item>

</layer-list>

And the code inside your layout xml:

<ProgressBar android:id=\"@+id/progressBar\"
    android:progressDrawable=\"@drawable/progress_bar_states\"
    android:layout_width=\"fill_parent\" android:layout_height=\"8dip\" 
    style=\"?android:attr/progressBarStyleHorizontal\" 
    android:indeterminateOnly=\"false\" 
    android:max=\"100\">
</ProgressBar>

Enjoy!



回答2:

I was having some trouble using an Indeterminate Progress Dialog with the solution here, after some work and trial and error I got it to work.

First, create the animation you want to use for the Progress Dialog. In my case I used 5 images.

../res/anim/progress_dialog_icon_drawable_animation.xml:

<animation-list xmlns:android=\"http://schemas.android.com/apk/res/android\">
    <item android:drawable=\"@drawable/icon_progress_dialog_drawable_1\" android:duration=\"150\" />
    <item android:drawable=\"@drawable/icon_progress_dialog_drawable_2\" android:duration=\"150\" />
    <item android:drawable=\"@drawable/icon_progress_dialog_drawable_3\" android:duration=\"150\" />
    <item android:drawable=\"@drawable/icon_progress_dialog_drawable_4\" android:duration=\"150\" />
    <item android:drawable=\"@drawable/icon_progress_dialog_drawable_5\" android:duration=\"150\" />
</animation-list>

Where you want to show a ProgressDialog:

dialog = new ProgressDialog(Context.this);
dialog.setIndeterminate(true);
dialog.setIndeterminateDrawable(getResources().getDrawable(R.anim.progress_dialog_icon_drawable_animation));
dialog.setMessage(\"Some Text\");
dialog.show();

This solution is really simple and worked for me, you could extend ProgressDialog and make it override the drawable internally, however, this was really too complicated for what I needed so I did not do it.



回答3:

Try setting:

android:indeterminateDrawable=\"@drawable/progress\" 

It worked for me. Here is also the code for progress.xml:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<rotate xmlns:android=\"http://schemas.android.com/apk/res/android\"
    android:pivotX=\"50%\" android:pivotY=\"50%\" android:fromDegrees=\"0\"
    android:toDegrees=\"360\">

    <shape android:shape=\"ring\" android:innerRadiusRatio=\"3\"
        android:thicknessRatio=\"8\" android:useLevel=\"false\">

        <size android:width=\"48dip\" android:height=\"48dip\" />

        <gradient android:type=\"sweep\" android:useLevel=\"false\"
            android:startColor=\"#4c737373\" android:centerColor=\"#4c737373\"
            android:centerY=\"0.50\" android:endColor=\"#ffffd300\" />

    </shape>

</rotate> 


回答4:

Your style should look like this:

<style parent=\"@android:style/Widget.ProgressBar\" name=\"customProgressBar\">
    <item name=\"android:indeterminateDrawable\">@anim/mp3</item>
</style>


回答5:

Custom progress with scale!

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<animation-list xmlns:android=\"http://schemas.android.com/apk/res/android\" >
    <item android:duration=\"150\">
        <scale
            android:drawable=\"@drawable/face_no_smile_eyes_off\"
            android:scaleGravity=\"center\" />
    </item>
    <item android:duration=\"150\">
        <scale
            android:drawable=\"@drawable/face_no_smile_eyes_on\"
            android:scaleGravity=\"center\" />
    </item>
    <item android:duration=\"150\">
        <scale
            android:drawable=\"@drawable/face_smile_eyes_off\"
            android:scaleGravity=\"center\" />
    </item>
    <item android:duration=\"150\">
        <scale
            android:drawable=\"@drawable/face_smile_eyes_on\"
            android:scaleGravity=\"center\" />
    </item>

</animation-list>


回答6:

i do your code .i can run but i need modify two places:

  1. name=\"android:indeterminateDrawable\" instead of android:progressDrawable

  2. modify name attrs.xml ---> styles.xml



回答7:

I\'m not sure but in this case you can still go with a complete customized AlertDialog by having a seperate layout file set in the alert dialog and set the animation for your imageview using part of your above code that should also do it!



回答8:

public class CustomProgressBar {
    private RelativeLayout rl;
    private ProgressBar mProgressBar;
    private Context mContext;
    private String color__ = \"#FF4081\";
    private ViewGroup layout;
    public CustomProgressBar (Context context, boolean isMiddle, ViewGroup layout) {
        initProgressBar(context, isMiddle, layout);
    }

    public CustomProgressBar (Context context, boolean isMiddle) {
        try {
            layout = (ViewGroup) ((Activity) context).findViewById(android.R.id.content).getRootView();
        } catch (Exception e) {
            e.printStackTrace();
        }
        initProgressBar(context, isMiddle, layout);
    }

    void initProgressBar(Context context, boolean isMiddle, ViewGroup layout) {
        mContext = context;
        if (layout != null) {
            int padding;
            if (isMiddle) {
                mProgressBar = new ProgressBar(context, null, android.R.attr.progressBarStyleSmall);
                // mProgressBar.setBackgroundResource(R.drawable.pb_custom_progress);//Color.parseColor(\"#55000000\")
                padding = context.getResources().getDimensionPixelOffset(R.dimen.padding);
            } else {
                padding = context.getResources().getDimensionPixelOffset(R.dimen.padding);
                mProgressBar = new ProgressBar(context, null, android.R.attr.progressBarStyleSmall);
            }
            mProgressBar.setPadding(padding, padding, padding, padding);
            mProgressBar.setBackgroundResource(R.drawable.pg_back);
            mProgressBar.setIndeterminate(true);
                try {
                    color__ = AppData.getTopColor(context);//UservaluesModel.getAppSettings().getSelectedColor();
                } catch (Exception e) {
                    color__ = \"#FF4081\";
                }
                int color = Color.parseColor(color__);
//                color=getContrastColor(color);
//                color__ = color__.replaceAll(\"#\", \"\");//R.color.colorAccent
                mProgressBar.getIndeterminateDrawable().setColorFilter(color, android.graphics.PorterDuff.Mode.SRC_ATOP);
            } 
            }

            RelativeLayout.LayoutParams params = new
                    RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            rl = new RelativeLayout(context);
            if (!isMiddle) {
                int valueInPixels = (int) context.getResources().getDimension(R.dimen.padding);
                lp.setMargins(0, 0, 0, (int) (valueInPixels / 1.5));//(int) Utils.convertDpToPixel(valueInPixels, context));
                rl.setClickable(false);
                lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            } else {
                rl.setGravity(Gravity.CENTER);
                rl.setClickable(true);
            }
            lp.addRule(RelativeLayout.CENTER_IN_PARENT);
            mProgressBar.setScaleY(1.55f);
            mProgressBar.setScaleX(1.55f);
            mProgressBar.setLayoutParams(lp);

            rl.addView(mProgressBar);
            layout.addView(rl, params);
        }
    }

    public void show() {
        if (mProgressBar != null)
            mProgressBar.setVisibility(View.VISIBLE);
    }

    public void hide() {
        if (mProgressBar != null) {
            rl.setClickable(false);
            mProgressBar.setVisibility(View.INVISIBLE);
        }
    }
}

And then call

customProgressBar = new CustomProgressBar (Activity, true);
customProgressBar .show();