用fragment怎么引入setcontentview_用textview+线程实现自定义进度条

文章目录

    • 1.activity_main.xml
    • 2.MianActivity

前几天一个朋友问我一下图片这个进度条怎么好实现

fee7dfb81d4ab96b1922d72e142b3ffe.png


他说他的思路是progressBar+OnDraw方法绘制文字
当时看到这个图,我第一个想法就是可以通过TextView,然后通过线程去动态改变控件的宽度
他说没怎么明白,然后我自己就写了个demo,就顺便更到博客上

总的来说呐,实现思路其实还是蛮简单,首先定义好自己想要的样式的进度条然后获取屏幕的宽度,减去你设置的外边距,也就是获取你进度条的总长度,然后算出每一个进度你需要的前进的宽度是多少,(因为这里是整数,所以在进度条满了的时候还需要补齐误差值),所有dp的单位根据屏幕密度换算成px单位,然后再通过线程通信动态更新进度条的进度,就O了。

1.activity_main.xml

直接贴代码了

<RelativeLayout 
    android:layout_width="match_parent"
    android:background="@color/colorWhite"
    android:layout_height="wrap_content"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_ma_progress_backgroud"
        android:layout_width="match_parent"
        android:layout_height="35dp"
        android:background="@drawable/progressbar_shape_gray"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:textColor="@color/colorWhite"
        android:gravity="right"
        android:layout_marginTop="30dp"
        android:paddingRight="5dp"
        android:textSize="14sp"
        />
    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv_ma_progress"
        android:layout_width="1dp"
        android:layout_height="35dp"
        android:background="@drawable/progressbar_shape_orange"
        android:textColor="@color/colorWhite"
        android:gravity="right|center_vertical"
        android:layout_marginTop="30dp"
        android:paddingRight="5dp"
        android:textSize="14sp"
        />

    </LinearLayout>

</RelativeLayout>

这边之所以用个线性布局,是为了方便后期动态设置这个texview的layoutParams属性

2.MianActivity

public class MainActivity extends AppCompatActivity {
    /**
     * 进度条
     */
    TextView tv_ma_progress;
    /**
     * 屏幕宽高
     */
    public static int screenWidth;
    /**
     * 总进度值
     */
    public int totalProgress = 100;
    /**
     * 起始进度值
     */
    public int beginProgress = 0;
    /**
     * 平均宽度
     */
    public int averageWidth = 1;
    /**
     * 因为求平均值的时候可能会除不尽  所以这里要求误差值
     */
    public int errorValue = 0;

    /**
     * 外边距magin   (dp)
     */
    public int marginSize = 30;

    /**
     * 屏幕密度
     */
    DisplayMetrics dm;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dm = new DisplayMetrics();
        dm = getResources().getDisplayMetrics();

        screenWidth = getWindowManager().getDefaultDisplay().getWidth();
        tv_ma_progress = findViewById(R.id.tv_ma_progress);
        averageWidth = (screenWidth-convertPx(marginSize)*2)/totalProgress;
        errorValue = screenWidth-convertPx(marginSize)*2 - averageWidth*totalProgress;

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (beginProgress<totalProgress){
                    beginProgress+=1;
                   try{
                       Thread.sleep(100);
                   }catch (Exception e){
                       e.printStackTrace();
                   }
                    Message message = new Message();
                    ProgressDto progressDto = new ProgressDto();
                    progressDto.setCurrentProgress(beginProgress);
                    int realShowWidth = averageWidth * beginProgress;
                    if(beginProgress>=totalProgress){
                        //因为之前求平均值时会有偏差,所以进度最后要加上误差值
                        realShowWidth = realShowWidth+errorValue;
                    }
                    progressDto.setCurrentWidth(realShowWidth);
                    message.obj = progressDto;
                    message.what = 1;
                    progressHandler.sendMessage(message);
                }


            }
        }).start();
    }

    Handler progressHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 1:
                    ProgressDto progressDto = (ProgressDto) msg.obj;
                    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(progressDto.getCurrentWidth(), convertPx(35));
                    layoutParams.setMargins(convertPx(marginSize), convertPx(marginSize), convertPx(marginSize), convertPx(marginSize));
                    if(progressDto.getCurrentProgress()<=5){
                        tv_ma_progress.setTextSize(TypedValue.COMPLEX_UNIT_SP, 4);
                    }else if(progressDto.getCurrentProgress()<=10){
                        tv_ma_progress.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
                    }else{
                        tv_ma_progress.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
                    }
                    tv_ma_progress.setLayoutParams(layoutParams);
                    tv_ma_progress.setText("+"+progressDto.getCurrentProgress());
                    break;
            }
        }
    };

    class ProgressDto{
        private int currentProgress;
        private int currentWidth;

        public int getCurrentProgress() {
            return currentProgress;
        }

        public void setCurrentProgress(int currentProgress) {
            this.currentProgress = currentProgress;
        }

        public int getCurrentWidth() {
            return currentWidth;
        }

        public void setCurrentWidth(int currentWidth) {
            this.currentWidth = currentWidth;
        }
    }


    /**
     * 根据dp转换成px
     * px = dp*ppi/160
     * dp = px / (ppi / 160)
     * px = sp*ppi/160
     *
     * @return
     */
    public int convertPx(int dp) {
        return dp * dm.densityDpi / 160;

    }

    
}

先贴上所有代码,再分析

这里主要是拿取屏幕宽度,和密度,拿密度其实主要是为了将dp转换成px,因为我们拿到的宽度是px为单位,我们动态设置控件高度宽度外边距之类的时候,其实都是px单位,但是我平时是用dp用习惯了,所以这边需要用到转换

 dm = new DisplayMetrics();
 dm = getResources().getDisplayMetrics();
 screenWidth = getWindowManager().getDefaultDisplay().getWidth();

    public int convertPx(int dp) {
        return dp * dm.densityDpi / 160;

    }

这句代码应该好理解,用屏幕的宽度减去两边设置的外边距再除以总进度,从而得到每一个进度所对应的宽度是多少

averageWidth = (screenWidth-convertPx(marginSize)*2)/totalProgress;

这句代码是在计算误差值,因为上一句求宽度平均值的时候,难免会有余数,所以这边暂且叫他误差值吧,进度满的时候,需要自动补齐

errorValue = screenWidth-convertPx(marginSize)*2 - averageWidth*totalProgress;

设置宽度的时候,我建议是直接用layoutParams,用以下两种形式设置宽度,不管用

tv_ma_progress.getLayoutParams().width;

tv_ma_progress.setWidth();

LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(progressDto.getCurrentWidth(), convertPx(35));
 layoutParams.setMargins(convertPx(marginSize), convertPx(marginSize), convertPx(marginSize), convertPx(marginSize));

这里其实就是动态设置字体大小的,本来没什么好说的,但是我之前踩过一个坑用的是tv_ma_progress.setTextSize()里面只有一个参数的,一个参数的确实会有问题,所以建议动态设置字体大小还是用下图这个

if(progressDto.getCurrentProgress()<=5){
	tv_ma_progress.setTextSize(TypedValue.COMPLEX_UNIT_SP, 4);
}else if(progressDto.getCurrentProgress()<=10){
   tv_ma_progress.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
}else{
   tv_ma_progress.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
}

github地址:https://github.com/carriefeng/SelfProgressDemo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值