使用权重实现柱形图

先上图
这里写图片描述
这里写图片描述

这里面的横向和竖向的都是使用权重实现的,一会会把代码贴出来,下面的那个viewpager是拽网上的

横向柱形图的实现

这里使用RecycleView实现的。其中item布局是关键。需要依据权重。不多说,直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
* 描述:
* 作者:Marc on 2016/6/17 11:13
* 邮箱:aliali_ha@yeah.net
*/
public class HoriAdapter extends RecyclerView.Adapter<HoriAdapter.MyViewHolder> {
private ArrayList<String> name;
private ArrayList<String> count;
private Context mContext;
public HoriAdapter(ArrayList<String> name, ArrayList<String> count, Context mContext) {
this.name = name;
this.count = count;
this.mContext = mContext;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.hori_item, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
String sName = name.get(position);
int sCount = Integer.parseInt(count.get(position));
int spaceHeight = ScreenUtils.dip2px(mContext, 20f);//条形高
int progressWeight = (int) (100 * 1.0 * sCount / 100);//计算权重
holder.progressBar.setLayoutParams(new LinearLayout.LayoutParams(0, spaceHeight, progressWeight));
holder.space.setLayoutParams(new LinearLayout.LayoutParams(0, spaceHeight, 100 - progressWeight));
holder.name.setText(sName);
holder.count.setText(sCount + "人");
}
@Override
public int getItemCount() {
return name.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.disease_type_name)
TextView name;
@Bind(R.id.progress)
View progressBar;
@Bind(R.id.disease_type_count)
TextView count;
@Bind(R.id.space)
View space;
public MyViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}

接下来是item的布局了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?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"
android:padding="15dp">
<TextView
android:id="@+id/disease_type_name"
android:layout_width="78sp"
android:layout_height="wrap_content"
android:layout_marginRight="27dp"
android:text="名字"
android:textColor="#797b80"
android:textSize="13sp" />
<!-- 进度条-->
<View
android:id="@+id/progress"
android:layout_width="1dp"
android:layout_height="6dp"
android:background="@drawable/count_type_progress" />
<!-- 显示数值-->
<TextView
android:id="@+id/disease_type_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:text="676人"
android:textColor="#333333"
android:textSize="13sp" />
<!--右侧空白 -->
<View
android:id="@+id/space"
android:layout_width="0dp"
android:layout_height="6dp" />
</LinearLayout>

其中count_type_progress的drawable文件

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners
android:bottomLeftRadius="5dp"
android:bottomRightRadius="5dp"
android:topLeftRadius="5dp"
android:topRightRadius="5dp" />
<solid android:color="@color/aat_blue" />
</shape>

其他的就是设置recycleview的内容了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mRecycleView.setHasFixedSize(true);
mManager = new LinearLayoutManager(this);
mRecycleView.setItemAnimator(new DefaultItemAnimator());
mRecycleView.setLayoutManager(mManager);
mHoriAdapter = new HoriAdapter(name, count, this);
mRecycleView.setAdapter(mHoriAdapter);
布局
<android.support.v7.widget.RecyclerView
android:id="@+id/hori_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:scrollbars="vertical"
/>

上面是实现的横向的柱形图的样子

下面实现纵向的柱形图的样子(PS:因为项目需要的没那么麻烦,所以没考虑用图表实现)

关键也是权重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class Hori2Adapter extends RecyclerView.Adapter<Hori2Adapter.MyViewHolder> {
private ArrayList<String> name;
private ArrayList<String> count;
private Context mContext;
public Hori2Adapter(ArrayList<String> name, ArrayList<String> count, Context mContext) {
this.name = name;
this.count = count;
this.mContext = mContext;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.hori_item_vertial, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
String sName = name.get(position);
int sCount = Integer.parseInt(count.get(position));
int spaceWidth = ScreenUtils.dip2px(mContext, 20f);//条形宽度
int progressWeight = (int) (100 * 1.0 * sCount / 100);//计算权重 //这个100 你可以设置成你们数据的最大值
//关键地方了
holder.progressBar.setLayoutParams(new LinearLayout.LayoutParams(spaceWidth, 0, progressWeight));
holder.space.setLayoutParams(new LinearLayout.LayoutParams(spaceWidth, 0, 100 - progressWeight));
holder.grade.setText(sName);
holder.count.setText(sCount + "人");
}
@Override
public int getItemCount() {
return name.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.tv_grade)
TextView grade;
@Bind(R.id.progress)
View progressBar;
@Bind(R.id.tv_type_count)
TextView count;
@Bind(R.id.space)
View space;
public MyViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//布局
<android.support.v7.widget.RecyclerView
android:id="@+id/hori_recyclerview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="5dp"
android:scrollbars="horizontal" />
//代码中
mRecycleView.setHasFixedSize(true);
mManager = new LinearLayoutManager(getActivity());
mManager.setOrientation(LinearLayoutManager.HORIZONTAL);//横向
mRecycleView.setItemAnimator(new DefaultItemAnimator());
mRecycleView.setLayoutManager(mManager);
mAdapter = new Hori2Adapter(mName, mCount, getActivity());
mRecycleView.setAdapter(mAdapter);
//item条目布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:orientation="vertical"
android:padding="15dp">
//空白占比
<View
android:id="@+id/space"
android:layout_width="6dp"
android:layout_height="0dp" />
<!-- 显示人数-->
<TextView
android:id="@+id/tv_type_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="15人"
android:textColor="#797b80"
android:textSize="13sp" />
<!-- 具体进度-->
<View
android:id="@+id/progress"
android:layout_width="6dp"
android:layout_height="1dp"
android:background="@drawable/count_type_progress" />
<TextView
android:id="@+id/tv_grade"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:text="高一"
android:textColor="#333333"
android:textSize="13sp" />
</LinearLayout>

这样子就实现了 纵向的柱形图
最下面的那个类似QQ附近人的。是看网上帖子,使用viewpager实现的,也一并贴出来
首先是自定义的VIEWPAGER
``java
/* 使用viewpager实现类似QQ附近的人 /
public class CustomViewPager extends ViewPager {
private long downTime;
private float LastX;
private float mSpeed;

public CustomViewPager(Context context) {
    super(context);
}

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

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    float x = ev.getX();
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downTime = System.currentTimeMillis();
            LastX = x;
            break;
        case MotionEvent.ACTION_MOVE:
            x = ev.getX();
            break;
        case MotionEvent.ACTION_UP:
            //计算得到手指从按下到离开的滑动速度
            mSpeed = (x - LastX) * 1000 / (System.currentTimeMillis() - downTime);
            break;
    }
    return super.dispatchTouchEvent(ev);
}

public float getSpeed() {
    return mSpeed;
}

public void setSpeed(float mSpeed) {
    this.mSpeed = mSpeed;
}
}

page切换动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.70f;
private static final float MIN_ALPHA = 0.5f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(MIN_ALPHA);
view.setScaleX(MIN_SCALE);
view.setScaleY(MIN_SCALE);
} else if (position <= 1) { // [-1,1]
// Modify the default slide transition to shrink the page as well
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
view.setScaleX(1 + 0.3f * position);
view.setScaleY(1 + 0.3f * position);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
view.setScaleX(1 - 0.3f * position);
view.setScaleY(1 - 0.3f * position);
}
// Scale the page down (between MIN_SCALE and 1)
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setScaleX(MIN_SCALE);
view.setScaleY(MIN_SCALE);
view.setAlpha(MIN_ALPHA);
}
}
}

手势滑动类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class FixedSpeedScroller extends Scroller {
private int mDuration = 1000;
public FixedSpeedScroller(Context context, AccelerateInterpolator accelerateInterpolator) {
super(context,accelerateInterpolator);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy) {
super.startScroll(startX, startY, dx, dy,mDuration);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, mDuration);
}
public void setmDuration(int time) {
mDuration = time;
}
public int getmDuration() {
return mDuration;
}
}

完整的xml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?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="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/hori_recyclerview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="5dp"
android:scrollbars="horizontal" />
<View
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="@android:color/holo_red_light" />
<RelativeLayout
android:id="@+id/ry_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="25dp"
android:layout_weight="1"
android:clipChildren="false">
<com.marc.chatpicture.widget.CustomViewPager
android:id="@+id/vp"
android:layout_width="130dp"
android:layout_height="160dp"
android:layout_centerInParent="true"
android:layout_marginLeft="120dp"
android:layout_marginRight="120dp" />
</RelativeLayout>
</LinearLayout>

viewpager适配器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
* 描述:
* 作者:Marc on 2016/6/24 09:53
* 邮箱:aliali_ha@yeah.net
*/
public class ViewpagerAdapter extends PagerAdapter {
private SparseArray<Info> mDatas;
private Context mContext;
private LayoutInflater inflater;
public ViewpagerAdapter(SparseArray<Info> mDatas, Context mContext) {
this.mDatas = mDatas;
this.mContext = mContext;
inflater = LayoutInflater.from(mContext);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
final Info info = mDatas.get(position);
//设置一大堆演示用的数据,数据啥的大家懂得,按照自己的来就好,这里就直接拿大神的了。项目紧
View view = inflater.inflate(R.layout.viewpager_layout,null);
ImageView ivPortrait = (ImageView) view.findViewById(R.id.iv);
ImageView ivSex = (ImageView) view.findViewById(R.id.iv_sex);
TextView tvName = (TextView) view.findViewById(R.id.tv_name);
TextView tvDistance = (TextView) view.findViewById(R.id.tv_distance);
tvName.setText(info.getName());
tvDistance.setText(info.getDistance() + "km");
ivPortrait.setImageResource(info.getPortraitId());
if (info.getSex()) {
ivSex.setImageResource(R.drawable.girl);
} else {
ivSex.setImageResource(R.drawable.boy);
}
ivPortrait.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, "这是 " + info.getName() + " >.<", Toast.LENGTH_SHORT).show();
}
});
container.addView(view);
return view;
}
@Override
public int getCount() {
return mDatas.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = (View) object;
container.removeView(view);
}
}

Fragment中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/**
* 描述:
* 作者:Marc on 2016/6/24 08:50
* 邮箱:aliali_ha@yeah.net
*/
public class SampleFragment extends RxFragment implements ViewPager.OnPageChangeListener {
LinearLayoutManager mManager;
@Bind(R.id.hori_recyclerview)
RecyclerView mRecycleView;
@Bind(R.id.vp)
CustomViewPager viewPager;
@Bind(R.id.ry_container)
RelativeLayout ryContainer;
private ArrayList<String> mName;
private ArrayList<String> mCount;
private Hori2Adapter mAdapter;
private String[] mNames = {"ImmortalZ", "唐马儒", "王尼玛", "张全蛋", "蛋花", "王大锤", "叫兽", "哆啦A梦"};
private int[] mImgs = {R.drawable.len, R.drawable.leo, R.drawable.lep,
R.drawable.leq, R.drawable.ler, R.drawable.les, R.drawable.mln, R.drawable.mmz, R.drawable.mna,
R.drawable.mnj, R.drawable.leo, R.drawable.leq, R.drawable.les, R.drawable.lep};
private int mPosition;
private FixedSpeedScroller scroller;
private SparseArray<Info> mDatas = new SparseArray<>();
private ViewpagerAdapter mViewPagerAdapter;
private static final String TAG = "SampleFragment";
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_sample, null);
ButterKnife.bind(this, view);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData();
initRecycle();
/**
* 将Viewpager所在容器的事件分发交给ViewPager
*/
ryContainer.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return viewPager.dispatchTouchEvent(event);
}
});
}
private void initRecycle() {
mRecycleView.setHasFixedSize(true);
mManager = new LinearLayoutManager(getActivity());
mManager.setOrientation(LinearLayoutManager.HORIZONTAL);//横向
mRecycleView.setItemAnimator(new DefaultItemAnimator());
mRecycleView.setLayoutManager(mManager);
mAdapter = new Hori2Adapter(mName, mCount, getActivity());
mRecycleView.setAdapter(mAdapter);
mViewPagerAdapter = new ViewpagerAdapter(mDatas, getActivity());
viewPager.setAdapter(mViewPagerAdapter);
//设置缓存数为展示的数目
viewPager.setOffscreenPageLimit(mImgs.length);
viewPager.setPageMargin(getResources().getDimensionPixelOffset(R.dimen.viewpager_margin));
//设置切换动画
viewPager.setPageTransformer(true, new ZoomOutPageTransformer());
viewPager.addOnPageChangeListener(this);
setViewPagerSpeed(250);
}
/**
* 设置viewpager切换速度
*
* @param duration
*/
private void setViewPagerSpeed(int duration) {
try {
Field field = ViewPager.class.getDeclaredField("mScroller");
field.setAccessible(true);
scroller = new FixedSpeedScroller(getActivity(), new AccelerateInterpolator());
field.set(viewPager, scroller);
scroller.setmDuration(duration);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private void initData() {
mName = new ArrayList<>();
mCount = new ArrayList<>();
for (int i = 0; i < 10; i++) {
mName.add("MARC" + i);
mCount.add(new Random().nextInt(99) + "");
}
for (int i = 0; i < mImgs.length; i++) {
Info info = new Info();
info.setPortraitId(mImgs[i]);
info.setAge(((int) Math.random() * 25 + 16) + "岁");
info.setName(mNames[(int) (Math.random() * mNames.length)]);
info.setSex(i % 3 == 0 ? false : true);
info.setDistance(Math.round((Math.random() * 10) * 100) / 100);
mDatas.put(i, info);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
mPosition = position;
}
@Override
public void onPageSelected(int position) {
LogUtils.e(TAG, "当前位置 " + mPosition);
LogUtils.e(TAG, "速度 " + viewPager.getSpeed());
//当手指左滑速度大于2000时viewpager右滑(注意是item+2)
if (viewPager.getSpeed() < -1800) {
viewPager.setCurrentItem(mPosition + 2);
LogUtils.e(TAG, "位置 " + mPosition);
viewPager.setSpeed(0);
} else if (viewPager.getSpeed() > 1800 && mPosition > 0) {
//当手指右滑速度大于2000时viewpager左滑(注意item-1即可)
viewPager.setCurrentItem(mPosition - 1);
LogUtils.e(TAG, "位置 " + mPosition);
viewPager.setSpeed(0);
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
}

PS:网上的还有个雷达图,这里用不到,大家可以自行搜索

资源下载