先上图
这里面的横向和竖向的都是使用权重实现的,一会会把代码贴出来,下面的那个viewpager是拽网上的
横向柱形图的实现
这里使用RecycleView实现的。其中item布局是关键。需要依据权重。不多说,直接上代码
/**
* 描述:
* 作者: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的布局了。
<?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文件
<?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的内容了
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:因为项目需要的没那么麻烦,所以没考虑用图表实现)
关键也是权重
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);
}
}
}
//布局
<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切换动画
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);
}
}
}
手势滑动类
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文件
<?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适配器
/**
* 描述:
* 作者: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中
/**
* 描述:
* 作者: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:网上的还有个雷达图,这里用不到,大家可以自行搜索