這個圖表是根據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;
這樣比例變大了,就不會出現右邊的文字位置顯示不正確的情況的