这个图表是根据RecyclerView+ProgressBar结合,并根据数据的比例动态设置右边数字的marginLeft,并可以进行分页的图表列表
准备工作:
1、引用
compile 'cn.finalteam.loadingviewfinal:ultra-pull-to-refresh:1.0.1'
compile 'cn.finalteam.loadingviewfinal:loading-more-view:1.0.1'
compile 'com.zhy:base-rvadapter:3.0.3'
compile 'com.zhy:base-adapter:3.0.3'
compile 'com.jakewharton:butterknife:7.0.1'
2、主activity布局:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="com.zx.tourism.ChartActivity">
<cn.finalteam.loadingviewfinal.RecyclerViewFinal
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:descendantFocusability="beforeDescendants"
android:layout_height="match_parent"
android:cacheColorHint="#00000000"
app:loadMoreMode="click|scroll"
app:loadMoreView="cn.finalteam.loadingviewfinal.DefaultLoadMoreView"
app:noLoadMoreHideView="false" />
</FrameLayout>
3、listitem_chart.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_product_name"
android:layout_marginLeft="15dp"
android:layout_marginRight="5dp"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center_vertical|left"
android:singleLine="true"
android:textColor="#aaaaaa"
/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_top"
android:layout_width="1px"
android:layout_height="5dp"
android:background="#dddddd" />
<FrameLayout
android:paddingRight="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:id="@+id/pb_number"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="25dp"
android:max="100"
android:progress="40"
android:progressDrawable="@drawable/progressbar_color"
/>
<TextView
android:layout_gravity="center_vertical"
android:id="@+id/tv_boxing_number"
android:textSize="10sp"
android:textColor="#aaaaaa"
android:text="0"
android:layout_marginLeft="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
<TextView
android:id="@+id/tv_bottom"
android:layout_width="1px"
android:layout_height="5dp"
android:background="#dddddd" />
</LinearLayout>
</LinearLayout>
4、Chart.java
package com.zx.tourism;
import java.io.Serializable;
/**
* Created by user on 2017/8/15.
*/
public class Chart implements Serializable {
private String productName;
private int number;
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
5、progressbar_color.xml,控制背景
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 背景 gradient是渐变,corners定义的是圆角 -->
<item android:id="@android:id/background">
<shape>
<solid android:color="#ffffff" />
</shape>
</item>
<!-- 第二条进度条颜色 -->
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="10dip" />
<gradient
android:angle="90.0"
android:centerColor="@android:color/white"
android:centerY="0.45"
android:endColor="@android:color/white"
android:startColor="@android:color/white" />
</shape>
</clip>
</item>
<!-- 进度条 -->
<item android:id="@android:id/progress">
<clip>
<shape>
<solid android:color="#FF9c24" />
</shape>
</clip>
</item>
</layer-list>
通过layer-list控制progressBar的背景
准备工作做好了,下面看主Activity的实现
package com.zx.tourism;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.util.Log;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.zhy.adapter.recyclerview.CommonAdapter;
import com.zhy.adapter.recyclerview.base.ViewHolder;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import butterknife.Bind;
import butterknife.ButterKnife;
import cn.finalteam.loadingviewfinal.RecyclerViewFinal;
public class ChartActivity extends AppCompatActivity {
@Bind(R.id.rv_list)
RecyclerViewFinal mRvList;
private CommonAdapter mCommonAdapter;
private List<Chart> mList = new ArrayList<>();
private float mMaxNumber;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chart);
ButterKnife.bind(this);
initView();
for (int i = 0; i < 10; i++) {
Chart chart = new Chart();
chart.setProductName("产品" + i);
int number = new Random().nextInt(10000);
chart.setNumber(number);
mList.add(chart);
}
doSort();
int firstNumber = mList.get(0).getNumber();
//设置bar的最大值值 = 当前数据最大值 + 它的六分之一
// 以给右边数字提供足够的显示空间
mMaxNumber = firstNumber + firstNumber / 6;
}
//简单冒泡排序
private void doSort() {
for (int i = 0; i < mList.size() - 1; i++) {
for (int j = 0; j < mList.size() - i - 1; j++) {
if (mList.get(j).getNumber() < mList.get(j + 1).getNumber()) {
//临时保存第一个数
Chart temp = mList.get(j);
//第二个数和第一个数换位置
mList.set(j, mList.get(j + 1));
mList.set(j + 1, temp);
}
}
}
}
private void initView() {
mRvList.setLayoutManager(new LinearLayoutManager(this));
mCommonAdapter = new CommonAdapter<Chart>(this, R.layout.listitem_chart, mList) {
@Override
protected void convert(final ViewHolder holder, final Chart chart, final int position) {
final ProgressBar pbNumber = holder.getView(R.id.pb_number);
final TextView tvBoxingNumber = holder.getView(R.id.tv_boxing_number);
//设置bar右边的数值,通过post方法的到空间的宽度
pbNumber.post(new Runnable() {
@Override
public void run() {
//转到主线程
runOnUiThread(new Runnable() {
@Override
public void run() {
int number = Integer.parseInt(chart.getNumber() + "");
//得到当前值和最大值的比例
float proportion = number / mMaxNumber;
//当前ProgressBar的宽度*比例 = 居左边的距离
int margingLeft = (int) (pbNumber.getWidth() * proportion);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(margingLeft + 2, 0, 0, 0);
lp.gravity = Gravity.CENTER_VERTICAL;
tvBoxingNumber.setLayoutParams(lp);
holder.setText(R.id.tv_product_name, chart.getProductName());
holder.setText(R.id.tv_boxing_number, chart.getNumber() + "");
holder.setProgress(R.id.pb_number, number, (int) mMaxNumber);
}
});
}
});
}
};
mRvList.setAdapter(mCommonAdapter);
}
}
以上代码有2个关键点:
关键点1:
设置bar的最大值 = 当前数据最大值 + 它的六分之一
其中,这个六分之一就是给右边数字的宽度
关键点2:
通过View.post() 方法得到当前控件的宽度,根据数值的比例计算marginleft
关键点3:
如果number太小,那么比例就比较小,右边的数据就不够位置显示了
可以把number统一变大(即比例变大),但是右边的值不变
把下面的代码
//设置bar的最大值值 = 当前数据最大值 + 它的六分之一
// 以给右边数字提供足够的显示空间
mMaxNumber = firstNumber + firstNumber / 6;
换为
mMaxNumber = firstNumber * 100 + (firstNumber * 100) / 6;
把下面的代码:
int number = Integer.parseInt(chart.getNumber() + "");
//得到当前值和最大值的比例
float proportion = number / mMaxNumber;
换为:
int number = Integer.parseInt(chart.getNumber() + "");
//得到当前值和最大值的比例
number = number * 100;
float proportion = number / mMaxNumber;
这样比例变大了,就不会出现右边的文字位置显示不正确的情况的