如何将视图(TextView)约束到progressBar当前进度?

丹尼

我有一个正在处理的项目,在此项目中,我使用progressBars作为条形图,

也就是说:我得到了一个项目列表,然后检查哪个项目具有最大值,并将该最大值设置为所有进度条(项目)的最大进度,

然后我想显示每个项目的值(进度),但是我想将其附加到特定项目的进度,换句话说,我想在每个progressBar的每个进度的末尾显示进度值,

示例:最大进度29,不要介意百分比值或下面的标签

忙碌的猫

经过一些搜索,我设法使进度条垂直,但是我正在努力解决此问题,

有没有办法将某些东西附加到进度条的进度上?有没有办法引用xml中的进度?(最大值和不同项的进度仅在运行时才知道,并且之后保持不变)

谢谢。

Loremar Marabillas

使用正常的进度条来实现它并使其垂直,会使一切变得太复杂。因此,我的解决方案是创建一个自定义视图,该视图由一个带有ClipDrawable背景的视图(用于进度)和一个TextView(标签)组成。

完整代码:

LabeledVerticalProgressBar.java

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.widget.TextView;

import androidx.constraintlayout.widget.ConstraintLayout;

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID;

public class LabeledVerticalProgressBar extends ConstraintLayout {
    private TextView textView;
    private View progressView;

    private Drawable progressDrawable;
    private float min;
    private float max;
    private float progress;
    private int labelTextAppearanceId;
    private boolean isLabelAbove = true;
    private int numDecimals;
    private String unit = "";

    private int height;

    public LabeledVerticalProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        initViews();
        initAttributes(attrs);
        initProgress();
        initLabel();
    }

    private void initViews() {
        progressView = new View(getContext());
        progressView.setId(View.generateViewId());
        LayoutParams progressParams = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
        progressParams.topToTop = PARENT_ID;
        progressParams.bottomToBottom = PARENT_ID;
        progressParams.startToStart = PARENT_ID;
        progressParams.endToEnd = PARENT_ID;
        progressView.setLayoutParams(progressParams);

        textView = new TextView(getContext());
        int padding = (int)(4 * getResources().getDisplayMetrics().density);
        textView.setPadding(padding, padding, padding, padding);
        LayoutParams textParams = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
        textParams.startToStart = progressView.getId();
        textParams.endToEnd = progressView.getId();
        textParams.bottomToBottom = progressView.getId();
        textView.setLayoutParams(textParams);

        addView(progressView);
        addView(textView);

        setClipChildren(false);
        setClipToPadding(false);
    }

    private void initAttributes(AttributeSet attrs) {
        TypedArray a = getContext().getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.LabeledVerticalProgressBar,
                0, 0);
        try {
            progressDrawable = a.getDrawable(R.styleable.LabeledVerticalProgressBar_progress_drawable);
            min = a.getFloat(R.styleable.LabeledVerticalProgressBar_min, 0);
            max = a.getFloat(R.styleable.LabeledVerticalProgressBar_max, 100);
            progress = a.getFloat(R.styleable.LabeledVerticalProgressBar_progress, 0);

            initTextAppearance(a);

            int labelPos = a.getInt(R.styleable.LabeledVerticalProgressBar_label_position, 0);
            if (labelPos == 1) {
                isLabelAbove = false;
            }
            numDecimals = a.getInt(R.styleable.LabeledVerticalProgressBar_num_decimals, 0);
            unit = a.getString(R.styleable.LabeledVerticalProgressBar_unit);

            if (min >= max) {
                throw new IllegalArgumentException("max should be greater than min");
            }
            clampProgress();
        } finally {
            a.recycle();
        }
    }

    private void initTextAppearance(TypedArray a) {
        /*TypedValue styleId = new TypedValue();
        boolean resolved = getContext().getTheme().resolveAttribute(R.styleable.LabeledVerticalProgressBar_label_text_appearance,
                styleId, true);
        if (resolved) {
            labelTextAppearanceId = styleId.data;
        } else {
            labelTextAppearanceId = -1;
        }*/
        ColorStateList color = a.getColorStateList(R.styleable.LabeledVerticalProgressBar_label_text_color);
        int size = a.getDimensionPixelSize(R.styleable.LabeledVerticalProgressBar_label_text_size, -1);
        int style = a.getInt(R.styleable.LabeledVerticalProgressBar_label_text_style, -1);
        Drawable background = a.getDrawable(R.styleable.LabeledVerticalProgressBar_label_background);

        if (color != null) {
            textView.setTextColor(color);
        }
        if (size != -1) {
            textView.setTextSize(size);
        }
        if (style != -1) {
            switch (style) {
                case 0: textView.setTypeface(textView.getTypeface(), Typeface.NORMAL); break;
                case 1: textView.setTypeface(textView.getTypeface(), Typeface.BOLD); break;
                case 2: textView.setTypeface(textView.getTypeface(), Typeface.ITALIC); break;
                case 3: textView.setTypeface(textView.getTypeface(), Typeface.BOLD_ITALIC); break;
            }
        }
        if (background != null) {
            textView.setBackground(background);
        }
    }

    private void initProgress() {
        if (progressDrawable == null) {
            progressDrawable = initDefaultProgressDrawable();
        }
        updateProgressView();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        height = progressView.getMeasuredHeight();
        initLabel();
        if (isLabelAbove) {
            // Add top space for label when progress is at max.
            setPadding(0, textView.getMeasuredHeight(), 0, 0);
        }
        super.onLayout(changed, left, top, right, bottom);
    }

    private void initLabel() {
        updateLabel();
        /*if (labelTextAppearanceId != -1) {
            TextViewCompat.setTextAppearance(textView, labelTextAppearanceId);
        }*/
    }

    public void setProgress(float progress) {
        this.progress = progress;
        clampProgress();
        progressView.getBackground().setLevel(computeLevel());
        updateLabel();
    }

    public void setProgress(final float progress, boolean animate, int duration) {
        if (animate) {
            float end = clampProgress(progress);
            float start = this.progress;
            ValueAnimator animator = ValueAnimator.ofFloat(start, end);
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    LabeledVerticalProgressBar.this.progress = (float) animation.getAnimatedValue();
                    progressView.getBackground().setLevel(computeLevel());
                    updateLabel();
                }
            });
            animator.setDuration(duration);
            animator.start();

        } else {
            setProgress(progress);
        }
    }

    public void setMax(float max) {
        this.max = max;
        if (min >= max) {
            throw new IllegalArgumentException("max should be greater than min");
        }
        setProgress(progress);
    }

    public void setMin(float min) {
        this.min = min;
        if (min >= max) {
            throw new IllegalArgumentException("max should be greater than min");
        }
        setProgress(progress);
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }

    public void setProgressDrawableColor(int color) {
        progressDrawable = new ColorDrawable(color);
        updateProgressView();
    }

    public void setProgressDrawable(Drawable progressDrawable) {
        this.progressDrawable = progressDrawable;
        updateProgressView();
    }

    private void updateProgressView() {
        ClipDrawable clip = new ClipDrawable(progressDrawable, Gravity.BOTTOM, ClipDrawable.VERTICAL);
        progressView.setBackground(clip);
        clip.setLevel(computeLevel());
    }

    private void updateLabel() {
        float translation = computeLabelTranslation();
        if (isLabelAbove) {
            textView.setTranslationY(translation);
        } else {
            if (-translation > textView.getMeasuredHeight()) {
                textView.setTranslationY(translation + textView.getMeasuredHeight());
            } else {
                textView.setTranslationY(0);
            }
        }
        String progressStr = String.format("%." + numDecimals + "f", progress) + unit;
        textView.setText(progressStr);
    }

    private int computeLevel() {
        float fraction = computeProgressFraction();
        return (int) (fraction * 10000);
    }

    private float computeLabelTranslation() {
        return -computeProgressFraction() * height;
    }

    private float computeProgressFraction() {
        clampProgress();
        return (progress - min) / (max - min);
    }

    private Drawable initDefaultProgressDrawable() {
        int colorAttr = getContext().getResources().getIdentifier("colorPrimary",
                "attr", getContext().getPackageName());
        TypedValue outValue = new TypedValue();
        getContext().getTheme().resolveAttribute(colorAttr, outValue, true);
        return new ColorDrawable(outValue.data);
    }

    private void clampProgress() {
        if (progress > max) {
            progress = max;
        } else if (progress < min) {
            progress = min;
        }
    }

    private float clampProgress(float progress) {
        if (progress > max) {
            return max;
        } else if (progress < min) {
            return min;
        } else {
            return progress;
        }
    }
}

attrs.xml

<resources>
    <declare-styleable name="LabeledVerticalProgressBar">
        <attr name="progress_drawable" format="reference|color"/>
        <attr name="min" format="float"/>
        <attr name="max" format="float"/>
        <attr name="progress" format="float"/>
        <attr name="label_text_appearance" format="reference"/>
        <attr name="label_text_color" format="color"/>
        <attr name="label_text_size" format="dimension"/>
        <attr name="label_text_style" format="enum">
            <enum name="normal" value="0"/>
            <enum name="bold" value="1"/>
            <enum name="italic" value="2"/>
            <enum name="bold_italic" value="3"/>
        </attr>
        <attr name="label_background" format="reference|color"/>
        <attr name="label_position" format="enum">
            <enum name="above" value="0"/>
            <enum name="below" value="1"/>
        </attr>

        <!--Number of displayed decimal places for label-->
        <attr name="num_decimals" format="integer"/>

        <attr name="unit" format="string"/>
    </declare-styleable>
</resources>

用法:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <marabillas.loremar.bindtextviewandprogressbar.LabeledVerticalProgressBar
        android:id="@+id/progressBar"
        android:layout_width="80dp"
        android:layout_height="480dp"
        android:background="#ddd"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:progress_drawable="#6a0dad"
        app:label_text_color="#fff"
        app:label_text_size="24sp"
        app:label_text_style="bold"
        app:label_background="#4ccc"
        app:label_position="below"
        app:min="20"
        app:max="500"
        app:progress="20"
        app:num_decimals="0"
        app:unit="%"/>

</androidx.constraintlayout.widget.ConstraintLayout>
@Override
    protected void onStart() {
        super.onStart();
        final LabeledVerticalProgressBar progressBar = findViewById(R.id.progressBar);
        progressBar.setProgress(500, true, 3000);

        Handler handler = new Handler(Looper.getMainLooper());

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                progressBar.setProgressDrawableColor(Color.GREEN);
            }
        }, 2000);

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                GradientDrawable gradient = new GradientDrawable();
                int color1 = Color.HSVToColor(new float[]{240f, 1f, 1f});
                int color2 = Color.HSVToColor(new float[]{240f, 1f, 0.5f});
                int[] colors = { color1, color2, color1};
                gradient.setColors(colors);
                gradient.setGradientType(GradientDrawable.LINEAR_GRADIENT);
                gradient.setOrientation(GradientDrawable.Orientation.LEFT_RIGHT);
                progressBar.setProgressDrawable(gradient);

                progressBar.setMax(2000);
                progressBar.setProgress(4000);
                progressBar.setMin(1000);
                progressBar.setUnit("");
                progressBar.setProgress(1500, true, 3000);
            }
        }, 3000);
    }

结果:

在此处输入图片说明

您可以用于setProgess()设置进度而无需动画或传递falseanimate参数。

到目前为止,我似乎无法使标签工作显示文本。

我认为通过一些编辑,您也可以将其水平放置。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何将视图约束到另一个视图底部的中心?

来自分类Dev

如何将视图放置在TextView的右侧

来自分类Dev

如何检查URLSession.dataTaskPublisher的当前进度?

来自分类Dev

如何将文件下载与进度视图链接

来自分类Dev

如何将数据从父视图传递到子视图?

来自分类Dev

如何将图像从集合视图传递到集合视图

来自分类Dev

如何将IB中的自动布局约束从一个视图复制到另一个视图?

来自分类Dev

如何将当前对象绑定到文本输入?

来自分类Dev

如何将canvas元素嵌入到当前网页的顶部?

来自分类Dev

如何将当前日期传递到查询中?

来自分类Dev

如何将Filezilla升级到当前版本?

来自分类Dev

如何将root的权限复制到当前用户?

来自分类Dev

如何将TextView的末端边缘定位到布局的中心?

来自分类Dev

如何将pdf文档显示到TextView中?

来自分类Dev

如何平滑地为SendingProgressView的当前进度设置动画?

来自分类Dev

进度条未显示当前进度

来自分类Dev

如何将Laravel变量传递到AngularJS视图中?

来自分类Dev

如何将值从NSTabViewController传递到子视图?

来自分类Dev

如何将包含列表的字典绑定到网格视图

来自分类Dev

如何将模型传递到局部视图

来自分类Dev

如何将列表从视图传递到控制器

来自分类Dev

如何将列表从视图传递到控制器

来自分类Dev

如何将属性传递到主干视图?

来自分类Dev

如何将复选框绑定到列表视图

来自分类Dev

如何将Kendo树视图绑定到文件目录

来自分类Dev

如何将模型连接/关联到视图?

来自分类Dev

如何将模型数据从局部视图传递到JavaScript?

来自分类Dev

如何将滚动视图放置到许多线性布局?

来自分类Dev

如何将列表从视图传递到控制器?

Related 相关文章

  1. 1

    如何将视图约束到另一个视图底部的中心?

  2. 2

    如何将视图放置在TextView的右侧

  3. 3

    如何检查URLSession.dataTaskPublisher的当前进度?

  4. 4

    如何将文件下载与进度视图链接

  5. 5

    如何将数据从父视图传递到子视图?

  6. 6

    如何将图像从集合视图传递到集合视图

  7. 7

    如何将IB中的自动布局约束从一个视图复制到另一个视图?

  8. 8

    如何将当前对象绑定到文本输入?

  9. 9

    如何将canvas元素嵌入到当前网页的顶部?

  10. 10

    如何将当前日期传递到查询中?

  11. 11

    如何将Filezilla升级到当前版本?

  12. 12

    如何将root的权限复制到当前用户?

  13. 13

    如何将TextView的末端边缘定位到布局的中心?

  14. 14

    如何将pdf文档显示到TextView中?

  15. 15

    如何平滑地为SendingProgressView的当前进度设置动画?

  16. 16

    进度条未显示当前进度

  17. 17

    如何将Laravel变量传递到AngularJS视图中?

  18. 18

    如何将值从NSTabViewController传递到子视图?

  19. 19

    如何将包含列表的字典绑定到网格视图

  20. 20

    如何将模型传递到局部视图

  21. 21

    如何将列表从视图传递到控制器

  22. 22

    如何将列表从视图传递到控制器

  23. 23

    如何将属性传递到主干视图?

  24. 24

    如何将复选框绑定到列表视图

  25. 25

    如何将Kendo树视图绑定到文件目录

  26. 26

    如何将模型连接/关联到视图?

  27. 27

    如何将模型数据从局部视图传递到JavaScript?

  28. 28

    如何将滚动视图放置到许多线性布局?

  29. 29

    如何将列表从视图传递到控制器?

热门标签

归档