Пользовательский Drawable для ProgressBar / ProgressDialog

128

Читая ограниченную документацию, предоставленную Google, у меня возникает ощущение, что можно изменить внешний вид (возможность рисования) ProgressBar / ProgressDialog, просто создав новый стиль и назначив его свойству style свойства ProgressBar. Но я не могу заставить это работать должным образом. Вот что я сделал до сих пор:

Я создал такую ​​форму (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>

затем создал анимацию (mp3.xml) следующим образом:

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

затем создал стиль (attrs.xml) следующим образом:

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

и в моем main.xml я установил такой стиль:

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

Но он по-прежнему показывает те же возможности рисования, что и раньше. Что я делаю не так?

Сэм
источник
Просто случайно просматривал образцы и наткнулся на ваш после прочтения этого . Надеюсь, это решит вашу проблему.
reuscam 09
Я знал, как создавать формы / градиенты / анимацию. Тот, который я создал выше, основан на публикации, на которую вы ссылаетесь (мне пришлось немного изменить ее, потому что она выглядит очень прерывистой и медленной). Я просто надеялся, что смогу добиться этого с помощью «стиля». В любом случае спасибо за ответ,
Сэм,
Если вы хотите полностью настроить индикатор выполнения и получить по-настоящему фантазию, взгляните на этот пост в блоге. Он может немного выходить за рамки того, что вам нужно, или может быть именно тем, что вы ищете. Надеюсь, поможет!
jagsaund

Ответы:

142

Я использовал следующее для создания настраиваемого индикатора выполнения.

Файл res/drawable/progress_bar_states.xmlобъявляет цвета разных состояний:

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

И код внутри вашего макета 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>

Наслаждайтесь!

Йона
источник
@YuliaRogovaya это потому, что чертежи не в элементах клипа? Я тоже не мог заставить его работать; подозреваю, что зажимной элемент является ключевым.
Эндрю Уайлд,
2
как это сделать для а ProgressDialog?
Nezam
@Nezam Я не могу дать вам точный код или образцы, но это то, что вам нужно сделать. Предоставьте настраиваемую тему для ProgressDialog. Настраиваемая тема будет определять стиль индикатора выполнения.
Jona
Было бы неплохо увидеть скриншот этой штуки в действии
QED
@Jona Я знаю, что это было какое-то время, но как я могу сделать этот растягиваемый меньше по высоте ??
леофонтес 05
55

У меня возникли проблемы с использованием диалогового окна неопределенного прогресса с решением здесь, после некоторой работы и проб и ошибок я заставил его работать.

Сначала создайте анимацию, которую хотите использовать в диалоге выполнения. В моем случае я использовал 5 изображений.

../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>

Где вы хотите показать 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();

Это решение действительно простое и сработало для меня, вы можете расширить ProgressDialog и заставить его переопределить возможность рисования внутри, однако это было слишком сложно для того, что мне было нужно, поэтому я не стал этого делать.

blindstuff
источник
1
Спасибо за внимание к "dialog.setIndeterminateDrawable ()"
Скоттиаб
Есть ли способ, чтобы в диалоговом окне было только изображение, чтобы не было сообщения, а можно было рисовать во всем диалоговом окне?
Diego
@Diego Я не пробовал, но не понимаю, почему. Вы пробовали использовать рисование, которое занимало бы желаемое пространство (т.е. имело длинное соотношение сторон) и не задавало текст в диалоговом окне?
blindstuff
41

Попробуйте установить:

android:indeterminateDrawable="@drawable/progress" 

У меня это сработало. Вот также код для 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> 
mudit
источник
3
Если вы хотите использовать возможность рисования, просто android:drawable=в теге поворота, а затем удалите форму. Наконец кто-то, кто отвечает на вопрос о вращающейся полосе выполнения.
MinceMan
2
Он устанавливает цвет, но индикатор выполнения не вращается
Crawler
Для быстрой регулировки скорости вращения android:toDegreesможно установить более высокое значение. Установка этого значения android:toDegrees="1080"увеличит вращение в 3 раза.
Левор
10

Ваш стиль должен выглядеть так:

<style parent="@android:style/Widget.ProgressBar" name="customProgressBar">
    <item name="android:indeterminateDrawable">@anim/mp3</item>
</style>
Виктор
источник
6

Я делаю ваш код. Я могу работать, но мне нужно изменить два места:

  1. name="android:indeterminateDrawable" вместо того android:progressDrawable

  2. изменить имя attrs.xml ---> styles.xml

pengwang
источник
вы измените свой android: startColor = "# 300000ff" на # FF00ff00, измените другой цвет
pengwang
6

Настраиваемый прогресс с масштабированием!

<?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>
Дмитрий
источник
0

Я не уверен, но в этом случае вы все равно можете использовать полностью настроенный AlertDialog, установив отдельный файл макета в диалоговом окне предупреждения и установив анимацию для вашего изображения, используя часть приведенного выше кода, который также должен это делать!

Джейшил Дэйв
источник
0
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);
        }
    }
}

А потом позвони

customProgressBar = new CustomProgressBar (Activity, true);
customProgressBar .show();
VV W
источник