Как создать круговую панель прогресса в Android, которая вращается на ней?

Я пытаюсь создать округленный прогресс. Это то, чего я хочу достичь.

Существует серое цветное фоновое кольцо. Вдобавок к этому появляется индикатор прогресса синего цвета, который перемещается по круговой траектории от 0 до 360 в 60 или любое количество секунд.

Введите описание изображения здесь

Вот мой примерный код.

<ProgressBar android:id="@+id/ProgressBar" android:layout_width="match_parent" android:layout_height="match_parent" style="?android:attr/progressBarStyleLarge" android:indeterminateDrawable="@drawable/progressBarBG" android:progress="50" /> 

Чтобы сделать это, в drawable "progressBarBG", я создаю список слоев и внутри этого списка слоев я даю два элемента, как показано.

 <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background"> <shape android:shape="ring" android:innerRadius="64dp" android:thickness="8dp" android:useLevel="false"> <solid android:color="@color/grey" /> </shape> </item> <item android:id="@android:id/progress"> <clip> <shape android:shape="ring" android:innerRadius="64dp" android:thickness="8dp" android:useLevel="false"> <solid android:color="@color/blue" /> </shape> </clip> </item> 

Теперь первое серое кольцо создается отлично. Тем не менее, синее кольцо начинается слева от выталкиваемого и идет вправо так же, как работает линейная панель прогресса. Это показывает, что он показывает 50% прогресса с красной стрелкой цвета, показывающей направление.

Введите описание изображения здесь

Я хочу переместить синий индикатор прогресса по круговой траектории, как ожидалось.

Solutions Collecting From Web of "Как создать круговую панель прогресса в Android, которая вращается на ней?"

Вот мое два решения.

Короткий ответ:

Вместо создания layer-list я разделил его на два файла. Один для ProgressBar и один для фона.

Это файл ProgressDrawable (папка @drawable): circle_progress_bar.xml

 <?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="270" android:toDegrees="270"> <shape android:innerRadiusRatio="2.5" android:shape="ring" android:thickness="1dp" android:useLevel="true"><!-- this line fixes the issue for lollipop api 21 --> <gradient android:angle="0" android:endColor="#007DD6" android:startColor="#007DD6" android:type="sweep" android:useLevel="false" /> </shape> </rotate> 1 <?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="270" android:toDegrees="270"> <shape android:innerRadiusRatio="2.5" android:shape="ring" android:thickness="1dp" android:useLevel="true"><!-- this line fixes the issue for lollipop api 21 --> <gradient android:angle="0" android:endColor="#007DD6" android:startColor="#007DD6" android:type="sweep" android:useLevel="false" /> </shape> </rotate> 

И это для его background (папка @drawable): circle_shape.xml

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring" android:innerRadiusRatio="2.5" android:thickness="1dp" android:useLevel="false"> <solid android:color="#CCC" /> </shape> 1 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring" android:innerRadiusRatio="2.5" android:thickness="1dp" android:useLevel="false"> <solid android:color="#CCC" /> </shape> 

И в конце, внутри макета, в котором вы работаете:

 <ProgressBar android:id="@+id/progressBar" android:layout_width="200dp" android:layout_height="200dp" android:indeterminate="false" android:progressDrawable="@drawable/circular_progress_bar" android:background="@drawable/circle_shape" style="?android:attr/progressBarStyleHorizontal" android:max="100" android:progress="65" /> 

Вот результат:

Введите описание изображения здесь

Длительный ответ:

Подкласс класса View, пользовательский вид

Введите описание изображения здесь

Вот полный проект по github

Я реализовал библиотеку с открытым исходным кодом на GitHub CircularProgressBar, которая делает именно то, что вы хотите простейшим способом:

Демо-версия Gif CircularProgressBar

ПРИМЕНЕНИЕ

Чтобы сделать круговой ProgressBar, добавьте CircularProgressBar в свой макет XML и добавьте библиотеку CircularProgressBar в ваш проектор, или вы также можете захватить его через Gradle:

 compile 'com.mikhaellopez:circularprogressbar:1.0.0' 

XML

 <com.mikhaellopez.circularprogressbar.CircularProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" app:background_progressbar_color="#FFCDD2" app:background_progressbar_width="5dp" app:progressbar_color="#F44336" app:progressbar_width="10dp" /> 

Вы должны использовать следующие свойства в своем XML, чтобы изменить CircularProgressBar.

Свойства:

  • app:progress (integer) >> default 0
  • app:progressbar_color (цвет) >> default BLACK
  • app:background_progressbar_color (цвет) >> по умолчанию GREY
  • app:progressbar_width (измерение) >> default 7dp
  • app:background_progressbar_width (измерение) >> default 3dp

ЯВА

 CircularProgressBar circularProgressBar = (CircularProgressBar)findViewById(R.id.yourCircularProgressbar); circularProgressBar.setColor(ContextCompat.getColor(this, R.color.progressBarColor)); circularProgressBar.setBackgroundColor(ContextCompat.getColor(this, R.color.backgroundProgressBarColor)); circularProgressBar.setProgressBarWidth(getResources().getDimension(R.dimen.progressBarWidth)); circularProgressBar.setBackgroundProgressBarWidth(getResources().getDimension(R.dimen.backgroundProgressBarWidth)); int animationDuration = 2500; // 2500ms = 2,5s circularProgressBar.setProgressWithAnimation(65, animationDuration); // Default duration = 1500ms 

Вилка или Загрузить эту библиотеку здесь >> https://github.com/lopspower/CircularProgressBar

Я сделал с легким способом:

Пожалуйста, проверьте скриншот за то же самое.

CustomProgressBarActivity.java :

 public class CustomProgressBarActivity extends AppCompatActivity { private TextView txtProgress; private ProgressBar progressBar; private int pStatus = 0; private Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_progressbar); txtProgress = (TextView) findViewById(R.id.txtProgress); progressBar = (ProgressBar) findViewById(R.id.progressBar); new Thread(new Runnable() { @Override public void run() { while (pStatus <= 100) { handler.post(new Runnable() { @Override public void run() { progressBar.setProgress(pStatus); txtProgress.setText(pStatus + " %"); } }); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } pStatus++; } } }).start(); } } 

Activity_custom_progressbar.xml :

 <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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.skholingua.android.custom_progressbar_circular.MainActivity" > <RelativeLayout android:layout_width="wrap_content" android:layout_centerInParent="true" android:layout_height="wrap_content"> <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="250dp" android:layout_height="250dp" android:layout_centerInParent="true" android:indeterminate="false" android:max="100" android:progress="0" android:progressDrawable="@drawable/custom_progressbar_drawable" android:secondaryProgress="0" /> <TextView android:id="@+id/txtProgress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/progressBar" android:layout_centerInParent="true" android:textAppearance="?android:attr/textAppearanceSmall" /> </RelativeLayout> </RelativeLayout> 

Custom_progressbar_drawable.xml :

 <?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="-90" android:pivotX="50%" android:pivotY="50%" android:toDegrees="270" > <shape android:shape="ring" android:useLevel="false" > <gradient android:centerY="0.5" android:endColor="#FA5858" android:startColor="#0099CC" android:type="sweep" android:useLevel="false" /> </shape> </rotate> 

Надеюсь, что это поможет вам.

Я написал подробный пример о круговом индикаторе прогресса в android здесь, на моем блоге demonuts.com . Вы также можете любить полный исходный код и объяснять там.

Вот как я сделал круговую панель прогресса с процентом внутри круга в чистом коде без какой-либо библиотеки.

Введите описание изображения здесь

Сначала создайте выталкиваемый файл с именем circular.xml

 <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/secondaryProgress"> <shape android:innerRadiusRatio="6" android:shape="ring" android:thicknessRatio="20.0" android:useLevel="true"> <gradient android:centerColor="#999999" android:endColor="#999999" android:startColor="#999999" android:type="sweep" /> </shape> </item> <item android:id="@android:id/progress"> <rotate android:fromDegrees="270" android:pivotX="50%" android:pivotY="50%" android:toDegrees="270"> <shape android:innerRadiusRatio="6" android:shape="ring" android:thicknessRatio="20.0" android:useLevel="true"> <rotate android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:toDegrees="360" /> <gradient android:centerColor="#00FF00" android:endColor="#00FF00" android:startColor="#00FF00" android:type="sweep" /> </shape> </rotate> </item> </layer-list> 

Теперь в вашем activity_main.xml добавьте следующее:

  <?xml version="1.0" encoding="utf-8"?> <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" android:background="@color/dialog" tools:context="com.example.parsaniahardik.progressanimation.MainActivity"> <ProgressBar android:id="@+id/circularProgressbar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="250dp" android:layout_height="250dp" android:indeterminate="false" android:max="100" android:progress="50" android:layout_centerInParent="true" android:progressDrawable="@drawable/circular" android:secondaryProgress="100" /> <ImageView android:layout_width="90dp" android:layout_height="90dp" android:background="@drawable/whitecircle" android:layout_centerInParent="true"/> <TextView android:id="@+id/tv" android:layout_width="250dp" android:layout_height="250dp" android:gravity="center" android:text="25%" android:layout_centerInParent="true" android:textColor="@color/colorPrimaryDark" android:textSize="20sp" /> </RelativeLayout> 

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

Введите описание изображения здесь

Вы можете изменить цвет этого изображения, чтобы установить собственный цвет в процентном тексте.

Теперь добавьте следующий код в MainActivity.java :

 import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.animation.DecelerateInterpolator; import android.widget.ProgressBar; import android.widget.TextView; public class MainActivity extends AppCompatActivity { int pStatus = 0; private Handler handler = new Handler(); TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Resources res = getResources(); Drawable drawable = res.getDrawable(R.drawable.circular); final ProgressBar mProgress = (ProgressBar) findViewById(R.id.circularProgressbar); mProgress.setProgress(0); // Main Progress mProgress.setSecondaryProgress(100); // Secondary Progress mProgress.setMax(100); // Maximum Progress mProgress.setProgressDrawable(drawable); /* ObjectAnimator animation = ObjectAnimator.ofInt(mProgress, "progress", 0, 100); animation.setDuration(50000); animation.setInterpolator(new DecelerateInterpolator()); animation.start();*/ tv = (TextView) findViewById(R.id.tv); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub while (pStatus < 100) { pStatus += 1; handler.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub mProgress.setProgress(pStatus); tv.setText(pStatus + "%"); } }); try { // Sleep for 200 milliseconds. // Just to display the progress slowly Thread.sleep(8); //thread will take approx 1.5 seconds to finish } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } } 

Если вы хотите сделать горизонтальную панель прогресса, следуйте по этой ссылке, у нее есть много ценных примеров с исходным кодом:
http://www.skholingua.com/android-basic/user-interface/form-widgets/progressbar

Я новичок, поэтому не могу прокомментировать, но решил поделиться ленивым исправлением. Я также использую оригинальный подход Педрама и просто столкнулся с той же проблемой Lollipop. Но у alanv в другом посте была исправлена ​​одна строка. Его некоторая ошибка или недосмотр в API21. Буквально просто добавьте android:useLevel="true" к вашему кругу progress xml. Новый подход Педрама по-прежнему является правильным решением, но я просто подумал, что я разделяю ленивое решение.

https://github.com/passsy/android-HoloCircularProgressBar – один из примеров библиотеки, которая делает это. Как заявила Tenfour04, это должно быть несколько обычным, поскольку это не поддерживается непосредственно из коробки. Если эта библиотека не ведет себя так, как вы хотите, вы можете разветвить ее и изменить детали, чтобы она работала по вашему вкусу. Если вы реализуете то, что другие могут затем повторно использовать, вы даже можете отправить запрос на вытягивание, чтобы вернуть его обратно!

Попробуйте этот метод для создания растрового изображения и установите его в режим просмотра изображений.

 private void circularImageBar(ImageView iv2, int i) { Bitmap b = Bitmap.createBitmap(300, 300,Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(b); Paint paint = new Paint(); paint.setColor(Color.parseColor("#c4c4c4")); paint.setStrokeWidth(10); paint.setStyle(Paint.Style.STROKE); canvas.drawCircle(150, 150, 140, paint); paint.setColor(Color.parseColor("#FFDB4C")); paint.setStrokeWidth(10); paint.setStyle(Paint.Style.FILL); final RectF oval = new RectF(); paint.setStyle(Paint.Style.STROKE); oval.set(10,10,290,290); canvas.drawArc(oval, 270, ((i*360)/100), false, paint); paint.setStrokeWidth(0); paint.setTextAlign(Align.CENTER); paint.setColor(Color.parseColor("#8E8E93")); paint.setTextSize(140); canvas.drawText(""+i, 150, 150+(paint.getTextSize()/3), paint); iv2.setImageBitmap(b); } 

@Pedram, ваше старое решение работает на самом деле отлично и в леденец (и лучше, чем новое, поскольку оно доступно повсеместно, в том числе в удаленных представлениях) просто измените код circular_progress_bar.xml на это:

 <?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="270" android:toDegrees="270"> <shape android:innerRadiusRatio="2.5" android:shape="ring" android:thickness="1dp" android:useLevel="true"> <!-- Just add this line --> <gradient android:angle="0" android:endColor="#007DD6" android:startColor="#007DD6" android:type="sweep" android:useLevel="false" /> </shape> </rotate> 1 <?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="270" android:toDegrees="270"> <shape android:innerRadiusRatio="2.5" android:shape="ring" android:thickness="1dp" android:useLevel="true"> <!-- Just add this line --> <gradient android:angle="0" android:endColor="#007DD6" android:startColor="#007DD6" android:type="sweep" android:useLevel="false" /> </shape> </rotate>