web-dev-qa-db-ja.com

それを回転させるアンドロイドで円形のプログラミングバーを作成する方法?

丸みを帯びたプログレスバーを作成しようとしています。これが私が達成したいことです

灰色の背景の輪があります。その上に、青い進捗バーが表示されます。進捗バーは60または何秒でも0から360までの円軌道で移動します。

enter image description here

これが私のサンプルコードです。

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

これを行うには、描画可能な「progressBarBG」で、レイヤリストを作成し、そのレイヤリスト内に、表示されているように2つの項目を指定します。

<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%の進捗状況で表示される方法です。

enter image description here

予想通り、青いプログレスバーを円を描くように移動します。

112

これが私の2つの解決策です。

簡単な答え:

layer-listを作成する代わりに、2つのファイルに分けました。 1つはProgressBarname__、もう1つはその背景です。

これはProgressDrawablename__ファイル(@drawableフォルダー)です。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"><!-- 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>

そしてこれはそのbackgroundname __(@ drawable folder)のためのものです: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>

そして最後に、作業しているレイアウトの内側に、

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

これが結果です。

result 1

長い答え:

Android.view.Viewを継承するカスタムビューを使う

result 2

これが完全なプロジェクトです github上

251

私は簡単な方法でやった:

スクリーンショットも同じようにチェックしてください。

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>

これがお役に立てば幸いです。

15
Hiren Patel

私は Androidの円形のプログレスバー ここに私のブログで詳細な例を書きました demonuts.com 。あなたは完全なソースコードと説明をそこで好むこともできます。

ライブラリを使わない純粋なコードで、円の内側にパーセンテージの付いた円形のプログレスバーを作成しました。

enter image description here

最初に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では、白い背景を持つ円形の画像を1つ使用して、白い背景をパーセントで表示しています。これがそのイメージです。

enter image description here

この画像の色を変更して、パーセントテキストの周囲にカスタムの色を設定できます。

最後に次のコードを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

15
Parsania Hardik

GitHubでオープンソースライブラリを実現しましたCircularProgressBar それはあなたが可能な限り最も単純な方法を望んでいることを正確に行います:

Gif demo CircularProgressBar

使用法

循環ProgressBarをレイアウトXMLにCircularProgressBarを追加し、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" />

CircularProgressBarを変更するには、XMLで次のプロパティを使用する必要があります。

プロパティ:

  • app:progress(integer)>>デフォルト0
  • app:progressbar_color(color)>>デフォルトのBLACK
  • app:background_progressbar_color(color)>>デフォルトGREY
  • app:progressbar_width(ディメンション)>>デフォルト7dp
  • app:background_progressbar_width(dimension)>>デフォルトの3dp

Java

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

11
lopez.mikhael

私は新しいのでコメントはできませんが、怠惰な修正を共有することを考えました。私もPedramのオリジナルのアプローチを使用して、そしてちょうど同じLollipop問題に出くわしました。しかし、 alanv が別の投稿で1行修正されました。そのある種のバグやAPI21の見落とし。サークルの進捗状況xmlに文字通りAndroid:useLevel="true"を追加するだけです。 Pedramの新しいアプローチはまだ適切な解決策ですが、私は怠惰な修正プログラムも共有すると思いました。

4
Miao Liu

https://github.com/passsy/Android-HoloCircularProgressBar はこれを行うライブラリの一例です。 Tenfour04が述べたように、これは箱から出して直接サポートされていないという点で、ややカスタムである必要があります。このライブラリが望みどおりに動作しない場合は、フォークして詳細を変更して好みに合うようにすることができます。他の人が再利用できるものを実装した場合は、プルリクエストを送信してマージすることもできます。

3
Travis

この方法を試してビットマップを作成し、それを画像ビューに設定します。

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);
}
3
mani

以下は、サークルの進行状況を表示する簡単なカスタムビューです。プロジェクトに合わせて、さらに変更および最適化できます。

class CircleProgressBar @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    private val backgroundWidth = 10f
    private val progressWidth = 20f

    private val backgroundPaint = Paint().apply {
        color = Color.LTGRAY
        style = Paint.Style.STROKE
        strokeWidth = backgroundWidth
        isAntiAlias = true
    }

    private val progressPaint = Paint().apply {
        color = Color.RED
        style = Paint.Style.STROKE
        strokeWidth = progressWidth
        isAntiAlias = true
    }

    var progress: Float = 0f
        set(value) {
            field = value
            invalidate()
        }

    private val oval = RectF()
    private var centerX: Float = 0f
    private var centerY: Float = 0f
    private var radius: Float = 0f

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        centerX = w.toFloat() / 2
        centerY = h.toFloat() / 2
        radius = w.toFloat() / 2 - progressWidth
        oval.set(centerX - radius,
                centerY - radius,
                centerX + radius,
                centerY + radius)
        super.onSizeChanged(w, h, oldw, oldh)
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        canvas?.drawCircle(centerX, centerY, radius, backgroundPaint)
        canvas?.drawArc(oval, 270f, 360f * progress, false, progressPaint)
    }
}

使用例

xml

<com.example.androidcircleprogressbar.CircleProgressBar
    Android:id="@+id/circle_progress"
    Android:layout_width="200dp"
    Android:layout_height="200dp" />

コトリン

class MainActivity : AppCompatActivity() {
    val TOTAL_TIME = 10 * 1000L

    override fun onCreate(savedInstanceState: Bundle?) {
        ...

        timeOutRemoveTimer.start()
    }

    private var timeOutRemoveTimer = object : CountDownTimer(TOTAL_TIME, 10) {
        override fun onFinish() {
            circle_progress.progress = 1f
        }

        override fun onTick(millisUntilFinished: Long) {
            circle_progress.progress = (TOTAL_TIME - millisUntilFinished).toFloat() / TOTAL_TIME
        }
    }
}

結果

2
Phan Van Linh

変化する

Android:useLevel="false"

Android:useLevel="true"

id="@Android:id/progressを持つ2番目のsahpeの場合

うまくいけばいい

1

@Pedram、あなたの古い解決策はLollipopでも実際にはうまく機能します(そしてリモートビューを含めて、どこでも使えるので新しい解決策よりも優れています):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
mim
package com.example.ankitrajpoot.myapplication;

import Android.app.Activity;
import Android.os.Bundle;
import Android.view.View;
import Android.widget.ProgressBar;


public class MainActivity extends Activity {

    private ProgressBar spinner;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        spinner=(ProgressBar)findViewById(R.id.progressBar);
        spinner.setVisibility(View.VISIBLE);
    }
}

xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/loadingPanel"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:gravity="center">

<ProgressBar
    Android:id="@+id/progressBar"

    Android:layout_width="48dp"
    style="?android:attr/progressBarStyleLarge"
    Android:layout_height="48dp"
    Android:indeterminateDrawable="@drawable/circular_progress_bar"
    Android:indeterminate="true" />
</RelativeLayout>





<?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="1080">
    <shape
        Android:shape="ring"
        Android:innerRadiusRatio="3"
        Android:thicknessRatio="8"
        Android:useLevel="false">

        <size
            Android:width="56dip"
            Android:height="56dip" />

        <gradient
            Android:type="sweep"
            Android:useLevel="false"
            Android:startColor="@Android:color/transparent"
            Android:endColor="#1e9dff"
            Android:angle="0"
            />

    </shape>
</rotate>
1
Ankit Rajpoot