计算7日签到
1.横向平分屏幕 计算每段距离大小
private void calcucateCirclePoints(List<String> viewData) {
if (null != viewData) {
//横向平分屏幕 计算每段距离大小
int intervalSize = viewData.size() + 1;
int onePiece = (viewWidth - signInBallRadio * 2 * viewData.size()) / intervalSize;
for (int i = 0; i < viewData.size(); i++) {
//每个六边形的 位置
Point circlePoint = new Point((i + 1) * onePiece + ((i + 1) * 2 - 1) * signInBallRadio, circleY);
//矩形的位置
Point descPoint = new Point((int) ((i + 1) * onePiece + ((i + 1) * 2 - 1) * signInBallRadio -
signInTextPaint.measureText(viewData.get(i)) / 2), descY);
//签到的矩形
RectF rectF = new RectF(0, viewHeight * SECTION_SCALE - signInBallRadio - signInRectHeight, circlePoint.x - signInBallRadio + 3, viewHeight * SECTION_SCALE - signInBallRadio);
//签到时候矩形的路径
Path selectPath = new Path();//选择矩形
selectPath.moveTo(i == 0 ? 0 : i * onePiece + (2 * i - 1) * signInBallRadio, circlePoint.y);
if (i == viewData.size() - 1) {
selectPath.lineTo(viewWidth, circlePoint.y);
} else {
selectPath.lineTo(circlePoint.x - signInBallRadio, circlePoint.y);
}
//没用到
Path signInPath = new Path();
signInPath.moveTo(circlePoint.x - signInBallRadio / 2, circlePoint.y);
signInPath.lineTo(circlePoint.x, circlePoint.y + signInBallRadio / 2);
signInPath.lineTo(circlePoint.x + signInBallRadio / 2, circlePoint.y - signInBallRadio + signInBallRadio / 2);
//大的六边形 路径
Path signInDoublePath = new Path();
signInDoublePath.moveTo((float) (circlePoint.x - signInBallRadio * 1.75 + 10), circlePoint.y);
signInDoublePath.lineTo((float) (circlePoint.x - signInBallRadio * 1.75 / 4), (float) (circlePoint.y + 1.65 * signInBallRadio / 2 - 5));
signInDoublePath.lineTo((float) (circlePoint.x + signInBallRadio * 1.75 / 2 + 5), (float) (circlePoint.y - 1.65 * signInBallRadio / 3 - 5));
signInDoublePath.lineTo((float) (circlePoint.x - signInBallRadio * 1.75 / 4), (float) (circlePoint.y + 1.65 * signInBallRadio / 4 * 3));
// signInDoublePath.lineTo(circlePoint.x + signInBallRadio , circlePoint.y - signInBallRadio + signInBallRadio);
signInDoublePath.close();
//小得六边形
Path sexanglePath = new Path();
sexanglePath.moveTo(circlePoint.x - signInBallRadio, circlePoint.y);
sexanglePath.lineTo(circlePoint.x - signInBallRadio / 2, circlePoint.y - 4 * signInBallRadio / 4);
sexanglePath.lineTo(circlePoint.x + signInBallRadio / 2, circlePoint.y - 4 * signInBallRadio / 4);
sexanglePath.lineTo(circlePoint.x + signInBallRadio, circlePoint.y);
sexanglePath.lineTo(circlePoint.x + signInBallRadio / 2, circlePoint.y + 4 * signInBallRadio / 4);
sexanglePath.lineTo(circlePoint.x - signInBallRadio / 2, circlePoint.y + 4 * signInBallRadio / 4);
sexanglePath.close();
// 大的六边形 做动画
Path sexangleDoublePath = new Path();
sexangleDoublePath.moveTo((float) (circlePoint.x - signInBallRadio * 1.75), circlePoint.y);
sexangleDoublePath.lineTo(circlePoint.x - signInBallRadio, (float) (circlePoint.y - (1.65 * signInBallRadio)));
sexangleDoublePath.lineTo(circlePoint.x + signInBallRadio, (float) (circlePoint.y - 1.65 * signInBallRadio));
sexangleDoublePath.lineTo((float) (circlePoint.x + signInBallRadio * 1.75), circlePoint.y);
sexangleDoublePath.lineTo(circlePoint.x + signInBallRadio, (float) (circlePoint.y + 1.65 * signInBallRadio));
sexangleDoublePath.lineTo(circlePoint.x - signInBallRadio, (float) (circlePoint.y + 1.65 * signInBallRadio));
sexangleDoublePath.close();
circlePoints.add(circlePoint);
descPoints.add(descPoint);
signInPbRectFs.add(rectF);
signInPaths.add(signInPath);
signInDoublePaths.add(signInDoublePath);
sexangleDoublePaths.add(sexangleDoublePath);
sexanglePaths.add(sexanglePath);
selectLinePath.add(selectPath);
}
//设置礼物图标
int new_W_H = circlePoints.get(viewData.size() - 1).y - signInBallRadio * 2;
desBitmap = new Rect(circlePoints.get(viewData.size() - 1).x - new_W_H / 2,
circlePoints.get(viewData.size() - 1).y - signInBallRadio * 2 - new_W_H,
circlePoints.get(viewData.size() - 1).x + new_W_H / 2,
circlePoints.get(viewData.size() - 1).y - signInBallRadio * 2);
}
}
2.测量
/**
* 测量
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int newHeight;
//如果不是精准模式 就使用默认的高度 具体用法请百度 MeasureSpec.getMode()
if (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED) {
newHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEF_HEIGHT, getResources().getDisplayMetrics());
heightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
//初始化一个画笔工具
private Paint createPaint(int paintColor, int textSize, Paint.Style style, int linWidth) {
Paint p = new Paint();
p.setColor(paintColor);
p.setAntiAlias(true);
p.setStrokeWidth(linWidth);
p.setDither(true);
p.setTextSize(textSize);
p.setStyle(style);
p.setStrokeCap(Paint.Cap.ROUND);
p.setStrokeJoin(Paint.Join.ROUND);
return p;
}
3.动态linerlayout
package com.example.horizontalscrollview.ui.adapter;
import android.content.Context;
import androidx.annotation.NonNull;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import com.example.horizontalscrollview.ui.adapter.DynamivAdapter;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义viewGroup 适配adapter
*
*/
public class GridViewGroup extends ViewGroup implements DynamivAdapter.OnDataChangeListen {
public DynamivAdapter dynamivAdapter;
public List<DynamivAdapter.ViewHolder> viewHolders = new ArrayList<>();
public GridViewGroup(Context context) {
super(context);
}
public GridViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public GridViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获得ViewGroup 宽高和测量模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
// measureChildren(widthMeasureSpec,heightMeasureSpec);
int cw=0;
int ch=0;
int count = getChildCount();
for (int i=0;i<count;i++){
View view = getChildAt(i);
cw = view.getMeasuredWidth();
ch = view.getMeasuredHeight();
Log.d("测试","---m"+cw+"----"+ch);
cw+=cw+cw;
ch+=ch;
}
Log.d("测试","---mm"+cw+"----"+ch);
//
// //计算所有的childview的宽高
setMeasuredDimension(cw, sizeHeight);
}
@Override
protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
int count = getChildCount();
Log.d("测试",count+"---");
int cw = 0;
int ch =0;
int cl= 0;
int ct = 0;
int cr=0;
int cb=0;
for (int j=0;j<count;j++){
View view = getChildAt(j);
cw = view.getMeasuredWidth();
ch = view.getMeasuredHeight();
Log.d("测试","cw"+cw);
if (j==0){
cl=0;
}else {
cl=(cl+cw);
}
cr=cl+cw;
cb=ch;
Log.d("测试",count+"---"+cl+"===="+ct+"--"+cr+"==="+cb);
view.layout(cl,ct,cr,cb);
}
}
public void setAdapter(DynamivAdapter dynamivAdapter){
Log.d("测试","-------");
this.dynamivAdapter = dynamivAdapter;
this.dynamivAdapter.setOnDataChangeListen(this);
changerAdapter();
}
private void changerAdapter() {
Log.d("测试","-------");
int srcCount = dynamivAdapter.getItemCount();
int destCount = this.getChildCount();
int maxCount = Math.max(srcCount,destCount);
Log.d("测试","-------"+destCount+"======"+srcCount);
for (int i=0;i<maxCount;i++){
Log.d("测试","-------++"+destCount+"======"+srcCount);
DynamivAdapter.ViewHolder viewHolder;
if (i < destCount){
viewHolder = viewHolders.get(i);
}else {
viewHolder = dynamivAdapter.onCreateViewHolder(this);
if (viewHolder.itemView.getParent() != null){
((ViewGroup)viewHolder.itemView.getParent()).removeAllViews();
}
addView(viewHolder.itemView);
viewHolders.add(i,viewHolder);
}
Log.d("测试","-------vh");
if (viewHolder != null){
if (i<srcCount){
dynamivAdapter.onBindViewHolder(viewHolder,i);
viewHolder.itemView.setVisibility(VISIBLE);
}else {
viewHolder.itemView.setVisibility(GONE);
}
}
}
requestLayout();
}
@Override
public void onChange() {
changerAdapter();
}
}
适配
package com.example.horizontalscrollview.ui.adapter;
import androidx.annotation.NonNull;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public abstract class DynamivAdapter <T,VH extends DynamivAdapter.ViewHolder> {
private final List<T> dataSouse = new ArrayList<>();
private OnDataChangeListen onDataChangeListen;
public void setOnDataChangeListen(OnDataChangeListen onDataChangeListen) {
this.onDataChangeListen = onDataChangeListen;
}
public void notifyDataChangeListen(){
if (onDataChangeListen != null){
onDataChangeListen.onChange();
}
}
public void sublist(List<T> newItems){
Log.d("测试","-------"+newItems.size());
dataSouse.clear();
dataSouse.addAll(newItems);
notifyDataChangeListen();
}
protected int getItemCount(){ return dataSouse.size();}
protected T getItem(int position){ return dataSouse.get(position);}
public abstract VH onCreateViewHolder(@NonNull ViewGroup parent);
public abstract void onBindViewHolder(@NonNull VH vh,int position);
public interface OnDataChangeListen{
void onChange();
}
public class ViewHolder{
public View itemView;
public ViewHolder(View itemView) {
this.itemView = itemView;
}
}
}
使用adapter
package com.example.horizontalscrollview.ui.adapter;
import androidx.annotation.NonNull;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.example.horizontalscrollview.R;
import com.example.horizontalscrollview.ui.model.Bean;
public class PageDynamicAdapter extends DynamivAdapter<Bean, PageDynamicAdapter.BaseViewHolder>{
private TextView tvName,tvAge;
private PageDynamicAdapter adapter;
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent) {
return new BaseViewHolder(View.inflate(parent.getContext(),R.layout.item_layout,parent));
}
@Override
public void onBindViewHolder(@NonNull BaseViewHolder baseViewHolder, int position) {
Bean bean = getItem(position);
Log.d("测试","+---------");
tvName.setText(bean.name);
tvAge.setText(bean.age);
}
public class BaseViewHolder extends DynamivAdapter.ViewHolder{
public BaseViewHolder(View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tv_name);
tvAge = itemView.findViewById(R.id.tv_age);
}
}
}
List<Bean> beans= new ArrayList<>();
Bean bean = new Bean();
bean.age=12;
bean.name="哈哈";
Bean bean1 = new Bean();
bean1.age=12;
bean1.name="哈哈";
beans.add(bean);
beans.add(bean1);
pageDynamicAdapter = new PageDynamicAdapter();
pageDynamicAdapter.setOnDataChangeListen(this);
gridViewGroup.setAdapter(pageDynamicAdapter);
pageDynamicAdapter.sublist(beans);
int maxWidth = 0;
int maxHeight = 0;
int childCount = getChildCount();
//计算宽度即可
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
if (view != null && view.getVisibility() != GONE) {
measureChild(view, widthMeasureSpec, heightMeasureSpec);
MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
maxWidth += view.getMeasuredWidth() + params.leftMargin + params.rightMargin;
maxHeight = Math.max(maxHeight, view.getMeasuredHeight() + params.topMargin + params.bottomMargin);
}
}
int resultWidth = maxWidth + getPaddingLeft() + getPaddingRight() + spacing * (childCount - 1);
int resultHeight = maxHeight + getPaddingTop() + getPaddingBottom();
setMeasuredDimension(resolveSize(resultWidth,widthMeasureSpec), resolveSize(resultHeight,heightMeasureSpec));
int left = getPaddingLeft();
int top = getPaddingTop();
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
if (view.getVisibility() == View.GONE) {
continue;
}
int lc = left + lp.leftMargin;
int tc = top + lp.topMargin;
int rc = lc + view.getMeasuredWidth();
int bc = tc + view.getMeasuredHeight();
view.layout(lc, tc, rc, bc);
left += view.getMeasuredWidth() + lp.leftMargin
+ lp.rightMargin + spacing;
}
测试代码
public class DynamicVerticalLayout extends ViewGroup implements DynamicAdapter.OnDataChangedListener {
private DynamicAdapter repeatAdapter;
private List<DynamicAdapter.ViewHolder> holderList = new ArrayList<>();
private int spacing = 0;
public DynamicVerticalLayout(Context context) {
this(context, null);
}
public DynamicVerticalLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, -1);
}
public DynamicVerticalLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DynamicVerticalLayout);
if (array != null) {
spacing = array.getDimensionPixelSize(R.styleable.DynamicVerticalLayout_android_spacing, 0);
array.recycle();
}
}
public void setAdapter(DynamicAdapter adapter) {
this.repeatAdapter = adapter;
this.repeatAdapter.setOnDataChangedListener(this);
changeAdapter();
}
private void changeAdapter() {
int srcCount = repeatAdapter.getItemCount();
int destCount = this.getChildCount();
int maxCount = Math.max(srcCount, destCount);
for (int i = 0; i < maxCount; i++) {
DynamicAdapter.ViewHolder viewHolder;
if (i < destCount) {
viewHolder = holderList.get(i);
} else {
viewHolder = repeatAdapter.onCreateViewHolder(this);
addView(viewHolder.itemView);
holderList.add(i, viewHolder);
}
if (viewHolder != null) {
if (i < srcCount) {
repeatAdapter.onBindViewHolder(viewHolder, i);
viewHolder.itemView.setVisibility(VISIBLE);
} else {
viewHolder.itemView.setVisibility(GONE);
}
}
}
requestLayout();
}
@Override
public void onChanged() {
changeAdapter();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int maxWidth = 0;
int maxHeight = 0;
int childCount = getChildCount();
//计算宽度即可
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
if (view != null && view.getVisibility() != GONE) {
MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
measureChild(view, widthMeasureSpec, heightMeasureSpec);
maxHeight += view.getMeasuredHeight() + params.topMargin + params.bottomMargin;
maxWidth = Math.max(maxWidth, view.getMeasuredWidth() + params.leftMargin + params.rightMargin);
}
}
int resultHeight = maxHeight + getPaddingTop() + getPaddingBottom() + spacing * (childCount - 1);
int resultWidth = maxWidth + getPaddingLeft() + getPaddingRight();
if (widthMode == MeasureSpec.AT_MOST) {
if (resultWidth > widthSize) {
resultWidth = widthSize;
}
}
setMeasuredDimension(resolveSize(resultWidth, widthMeasureSpec), resolveSize(resultHeight, heightMeasureSpec));
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left = getPaddingLeft();
int top = getPaddingTop();
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
if (view.getVisibility() == View.GONE) {
continue;
}
int lc = left + lp.leftMargin;
int tc = top + lp.topMargin;
int rc = lc + view.getMeasuredWidth();
int bc = tc + view.getMeasuredHeight();
view.layout(lc, tc, rc, bc);
top += view.getMeasuredHeight() + lp.topMargin
+ lp.bottomMargin + spacing;
}
}
@Override
protected LayoutParams generateLayoutParams(LayoutParams p) {
return new MarginLayoutParams(p);
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new MarginLayoutParams(MarginLayoutParams.MATCH_PARENT, MarginLayoutParams.WRAP_CONTENT);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
@Override
protected boolean checkLayoutParams(LayoutParams p) {
return p instanceof MarginLayoutParams;
}
}
public abstract class DynamicAdapter<T, VH extends DynamicAdapter.ViewHolder> {
private final List<T> mDataSource = new ArrayList<>();
private OnDataChangedListener mOnDataChangedListener;
interface OnDataChangedListener {
void onChanged();
}
private Path path;
public void setPath(Path path) {
this.path = path;
}
public Path getPath() {
return path;
}
void setOnDataChangedListener(OnDataChangedListener listener) {
mOnDataChangedListener = listener;
}
private void notifyDataSetChanged() {
if (mOnDataChangedListener != null) {
mOnDataChangedListener.onChanged();
}
}
public void submitList(List<T> newItems) {
mDataSource.clear();
mDataSource.addAll(newItems);
notifyDataSetChanged();
}
protected int getItemCount() {
return mDataSource.size();
}
protected T getItem(int position) {
return mDataSource.isEmpty() ? null : mDataSource.get(position);
}
public abstract VH onCreateViewHolder(@NonNull ViewGroup parent);
public abstract void onBindViewHolder(@NonNull VH vh, int position);
public static class ViewHolder {
public View itemView;
public ViewHolder(View itemView) {
this.itemView = itemView;
}
}
}
测试数据
public class FindInsuranceAdapter extends DynamicAdapter<HealthSecurity, FindInsuranceAdapter.ViewHolder>{
public OnItemOperateListener onItemOperateListener;
public void setOnItemOperateListener(OnItemOperateListener onItemOperateListener) {
this.onItemOperateListener = onItemOperateListener;
}
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_find_insurance, viewGroup, false);
return new ViewHolder(view, new SoftReference<>(this));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
HealthSecurity healthSecurity = getItem(position);
viewHolder.tvTitle.setText(healthSecurity.title);
viewHolder.ivInsuranceCover.setRoundImageUri(healthSecurity.imgUrl,R.drawable.ic_default, ScreenUtil.getPixDimension(R.dimen.w16));
viewHolder.tvContent.setText(healthSecurity.description);
if (!TextUtils.isEmpty(healthSecurity.labels)){
viewHolder.tvLabel.setVisibility(View.VISIBLE);
viewHolder.tvLabel.setText(healthSecurity.labels);
}else {
viewHolder.tvLabel.setVisibility(View.GONE);
}
viewHolder.relFindInsurance.setOnClickListener(v -> {
onItemOperateListener.onItemClick(healthSecurity);
});
}
public static class ViewHolder extends DynamicAdapter.ViewHolder implements OnPagerViewVisibleListener {
RemoteImageView ivInsuranceCover;
TextView tvTitle;
TextView tvContent;
TextView tvLabel;
RelativeLayout relFindInsurance;
private final FindInsuranceAdapter adapter;
public ViewHolder(@NonNull View itemView, SoftReference<FindInsuranceAdapter> softReference) {
super(itemView);
ivInsuranceCover = itemView.findViewById(R.id.iv_insurance_cover);
tvTitle = itemView.findViewById(R.id.tv_insurance_title);
tvContent = itemView.findViewById(R.id.tv_insurance_content);
tvLabel = itemView.findViewById(R.id.tv_insurance_label);
relFindInsurance = itemView.findViewById(R.id.rel_find_insurance);
adapter = softReference.get();
ViewAnalysis.with((PagerVisibleOwner) itemView.getContext()).listener(this).analyse(itemView);
}
@Override
public void onPagerViewVisibleChanged(boolean visible) {
// AnalysisPacket.obtain(AnalysisEventConstants.CHENGZHANGZHUSHOU_LIEBIAO_S)
// .addPath(adapter.getPath())
// .post();
}
}
public interface OnItemOperateListener {
void onItemClick(HealthSecurity healthSecurity);
void onItemShow(HealthSecurity healthSecurity);
}
}