package com.stategrid.echarge.wedgit.chart; import android.content.Context; import android.graphics.Canvas; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.util.Log; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.stategrid.echarge.R; import java.util.ArrayList; /** * 单线图 */ public class SingleFlogLineChart extends RelativeLayout { private Context mContext; private ArrayList<String> unitArrayList; private UnitAdapter adapter; private double itemWidth; private LinearLayoutManager manager; private boolean canRecyclScoll = false; private ArrayList<PointBean> firstPointBeans; private double unitItemWidth; private PointBean maxYPoint; public SingleFlogLineChart(Context context) { this(context, null); } public SingleFlogLineChart(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SingleFlogLineChart(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.mContext = context; } public void setCanRecyclScoll(boolean canRecyclScoll) { this.canRecyclScoll = canRecyclScoll; } public void setUnitArrayList(ArrayList<String> arrayList) { this.unitArrayList = arrayList; adapter.setArrayList(unitArrayList); adapter.notifyDataSetChanged(); } private RecyclerView unitRv; private LineRelativeLayout lineRelativeLayout; private SingleLineContainerView lineContainerView; private TextView leftTopTitle; private TextView rightTopTile; /** * set leftTitle * * @param leftTitle */ public void setLeftTopTitle(String leftTitle) { leftTopTitle.setText(leftTitle); } /** * set rightTitle * * @param rightTitle */ public void setRightTopTitle(String rightTitle) { rightTopTile.setText(rightTitle); } public void setFirstPointBeans(ArrayList<PointBean> firstPointBeans) { lineContainerView.setFirstPoints(firstPointBeans); this.firstPointBeans = firstPointBeans; } private LinearLayout bottomUnitLayout; private RecyclerView LeftUnitRv; private ObserverHorizontalScrollview scrollView; @Override protected void onFinishInflate() { super.onFinishInflate(); unitRv = findViewById(R.id.bottom_unit_rv); lineRelativeLayout = findViewById(R.id.chart_rl); scrollView = findViewById(R.id.horizon_scrollview); lineContainerView = findViewById(R.id.line_container_layout); bottomUnitLayout = findViewById(R.id.unit_llayout); LeftUnitRv = findViewById(R.id.left_unit_rv); manager = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false) { @Override public boolean canScrollHorizontally() { return canRecyclScoll; } }; unitRv.setLayoutManager(manager); LinearLayoutManager leftManager = new LinearLayoutManager(mContext) { @Override public boolean canScrollVertically() { return false; } }; LeftUnitRv.setLayoutManager(leftManager); scrollView.setmScrollViewListener(new ObserverHorizontalScrollview.ScrollViewListener() { private int sum; @Override public void onScrollChanged(int x, int y, int oldx, int oldy) { } @Override public void onScrollFinish(int scrollX) { canRecyclScoll = true; sum = (int) (scrollX / itemWidth); int halfItemWidth = (int) (itemWidth / 2); if (scrollX - itemWidth * sum > halfItemWidth) { sum++; } postDelayed(new Runnable() { @Override public void run() { scrollView.scrollTo((int) (itemWidth * sum), 0); } }, 50); // int firstItem = manager.findFirstVisibleItemPosition(); int lastItem = manager.findLastVisibleItemPosition(); Log.e("sum:", "" + sum + "--last--" + firstItem); //然后区分情况 if (sum <= firstItem) { //当要置顶的项在当前显示的第一个项的前面时 unitRv.scrollToPosition(sum); } else if (sum <= lastItem) { //当要置顶的项已经在屏幕上显示时,计算它离屏幕原点的距离 int left = unitRv.getChildAt(sum - firstItem).getLeft(); unitRv.scrollBy(left, 0); } else { //当要置顶的项在当前显示的最后一项的后面时 unitRv.scrollToPosition(sum + 6); //记录当前需要在RecyclerView滚动监听里面继续第二次滚动 } maxYPoint = null; //设置最大点的位置 int position = sum; for (int i = sum; i <= sum + 6; i++) { if (maxYPoint == null) { maxYPoint = firstPointBeans.get(i); } else { if (maxYPoint.getPercentY() < firstPointBeans.get(i).getPercentY()) { maxYPoint = firstPointBeans.get(i); position = i; } } } lineContainerView.setMaxPoint(maxYPoint); if (position == sum) { lineContainerView.setPosition(SingleLineContainerView.BITMAP_LEFT); } else if (position == sum + 6) { lineContainerView.setPosition(SingleLineContainerView.BITMAP_RIGHT); } else { lineContainerView.setPosition(SingleLineContainerView.BITMAP_MID); } lineContainerView.invalidate(); canRecyclScoll = false; } }); leftTopTitle = findViewById(R.id.left_top_title); rightTopTile = findViewById(R.id.right_top_title); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); int width = lineRelativeLayout.getMeasuredWidth(); itemWidth = width * 1.00 / 6; unitItemWidth = itemWidth - 5; unitRv.getLayoutParams().width = (int) (unitItemWidth * 7); Log.d("itemWidth-", itemWidth + ""); unitArrayList = new ArrayList<>(); for (int i = 1; i < 10; i++) { double num = 5 + i * 0.01; unitArrayList.add(num + ""); } for (int i = 10; i < 31; i++) { double num = 5 + i * 0.01; unitArrayList.add(num + ""); } adapter = new UnitAdapter(mContext, unitArrayList, unitItemWidth); unitRv.setAdapter(adapter); // unitRv.getLayoutParams().width = (int) (itemWidth*7); int height = LeftUnitRv.getMeasuredHeight(); // Log.d("height:", height + ""); double itemHeight = height * 1.0 / 7; ArrayList<String> leftList = new ArrayList<>(); for (int i = 70; i >= 10; i = i - 10) { leftList.add(i + ""); } LeftUnitAdapter leftUnitAdapter = new LeftUnitAdapter(mContext, leftList, itemHeight); LeftUnitRv.setAdapter(leftUnitAdapter); // firstPointBeans = new ArrayList<>(); // // Random random = new Random(); // for (int i = 0; i <= 30; i++) { // int percentY = (random.nextInt(4) + 2) * 10 - 2; // PointBean pointBean = new PointBean(i*0.2, percentY); // firstPointBeans.add(pointBean); // } // // // lineContainerView.setWidth((int) (itemWidth * 20)); // lineContainerView.setItemWidth(itemWidth); // lineContainerView.setFirstPoints(firstPointBeans); // lineContainerView.setFirstColor(Color.parseColor("#a1ffdd")); lineContainerView.setFirstColor(Color.RED); lineContainerView.setTextColor(Color.RED); // lineContainerView.invalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } }
//工具类
package com.stategrid.echarge.wedgit.chart; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.support.annotation.Nullable; import android.support.v7.widget.AppCompatTextView; import android.util.AttributeSet; import com.stategrid.echarge.R; import java.util.ArrayList; public class SingleLineContainerView extends AppCompatTextView { private Context mContext; private Paint firstLinePaint; private Paint textPaint; private double itemWidth; private String str = "60"; private ArrayList<PointBean> firstPoints; private PointBean maxPoint; private int firstColor = Color.parseColor("#0a856f"); private Bitmap bitmap; private Bitmap leftBitmap; private Bitmap rightBitmap; //bitmap 状态值 public static final int BITMAP_LEFT = 0; public static final int BITMAP_MID = 1; public static final int BITMAP_RIGHT = 2; private int position = BITMAP_MID; public void setFirstColor(int firstColor) { this.firstColor = firstColor; firstLinePaint.setColor(firstColor); } public SingleLineContainerView(Context context) { this(context, null); } public SingleLineContainerView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public void setPosition(int position) { this.position = position; } public SingleLineContainerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setWillNotDraw(false); this.mContext = context; //画笔 firstLinePaint = new Paint(); firstLinePaint.setAntiAlias(true); firstLinePaint.setStrokeWidth(3); firstLinePaint.setColor(firstColor); firstLinePaint.setStyle(Paint.Style.FILL_AND_STROKE); textPaint = new Paint(); textPaint.setStrokeWidth(3); textPaint.setTextSize(getTextSize()); textPaint.setColor(Color.parseColor("#ff41c496")); textPaint.setTextAlign(Paint.Align.LEFT); textPaint.setStyle(Paint.Style.FILL); bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_qipao); leftBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_qipao_left); rightBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_qipao_right); } public double getItemWidth() { return itemWidth; } public void setItemWidth(double itemWidth) { this.itemWidth = itemWidth; } public ArrayList<PointBean> getFirstPoints() { return firstPoints; } public void setFirstPoints(ArrayList<PointBean> firstPoints) { this.firstPoints = firstPoints; invalidate(); } public PointBean getMaxPoint() { return maxPoint; } public void setMaxPoint(PointBean maxPoint) { this.maxPoint = maxPoint; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int height = getMeasuredHeight(); double dy = (height * 1.000) / 100; if (firstPoints != null) { float firstPts[] = new float[(firstPoints.size() - 1) * 4]; if (firstPoints.size() > 1) { for (int i = 0; i < firstPoints.size() - 1; i++) { firstPts[4 * i] = (float) (firstPoints.get(i).getPercentX() * itemWidth); firstPts[4 * i + 1] = (float) ((100 - firstPoints.get(i).getPercentY()) * dy); firstPts[4 * i + 2] = (float) (firstPoints.get(i + 1).getPercentX() * itemWidth); firstPts[4 * i + 3] = (float) ((100 - firstPoints.get(i + 1).getPercentY()) * dy); } canvas.drawLines(firstPts, firstLinePaint); } } // maxPoint = firstPoints.get(6); // maxPoint.setNumY(60); // position = 2; if (maxPoint != null) { float left = (float) (maxPoint.getPercentX() * itemWidth); if (position == BITMAP_MID) { float hight = (float) ((100 - maxPoint.getPercentY()) * dy) - 5; int bmpWidth = bitmap.getWidth(); int bmpHeight = bitmap.getHeight(); canvas.drawBitmap(bitmap, left - bmpWidth / 2, hight - bmpHeight, firstLinePaint); Rect bounds = new Rect(); textPaint.getTextBounds(str, 0, str.length(), bounds); canvas.drawText(maxPoint.getNumY()+"", left - bounds.width() / 2, hight - bmpHeight / 2 + 2, textPaint); } else if (position == BITMAP_LEFT) { float hight = (float) ((100 - maxPoint.getPercentY()) * dy); int bmpWidth = leftBitmap.getWidth(); int bmpHeight = leftBitmap.getHeight(); canvas.drawBitmap(leftBitmap, left, hight - bmpHeight, firstLinePaint); Rect bounds = new Rect(); textPaint.getTextBounds(str, 0, str.length(), bounds); canvas.drawText(maxPoint.getNumY()+"", left - bounds.width() / 2 + bmpWidth / 2, hight - bmpHeight / 2 + 2, textPaint); } else { float hight = (float) ((100 - maxPoint.getPercentY()) * dy); int bmpWidth = rightBitmap.getWidth(); int bmpHeight = rightBitmap.getHeight(); canvas.drawBitmap(rightBitmap, left - bmpWidth, hight - bmpHeight, firstLinePaint); Rect bounds = new Rect(); textPaint.getTextBounds(str, 0, str.length(), bounds); canvas.drawText(maxPoint.getNumY()+"", left - bounds.width() / 2 - bmpWidth / 2, hight - bmpHeight / 2 + 2, textPaint); } } } }
package com.stategrid.echarge.wedgit.chart; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.stategrid.echarge.R; import java.util.ArrayList; /** * 底部刻度adpater */ public class SingleLineUnitAdapter extends RecyclerView.Adapter<SingleLineUnitAdapter.MyViewHolder> { private Context mContext; private ArrayList<String> arrayList; private double itemWidth; public SingleLineUnitAdapter(Context mContext, ArrayList<String> arrayList, double itemWidth) { this.mContext = mContext; this.arrayList = arrayList; this.itemWidth = itemWidth; } public void setItemWidth(double itemWidth) { this.itemWidth = itemWidth; } public void setArrayList(ArrayList<String> arrayList) { this.arrayList = arrayList; notifyDataSetChanged(); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_single_unit_layout, parent, false); view.findViewById(R.id.tv_unit).getLayoutParams().width = (int) itemWidth; return new MyViewHolder(view); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.textView.setText(arrayList.get(position)); } @Override public int getItemCount() { return arrayList == null ? 0 : arrayList.size(); } class MyViewHolder extends RecyclerView.ViewHolder { private TextView textView; public MyViewHolder(View itemView) { super(itemView); textView = itemView.findViewById(R.id.tv_unit); } } }
package com.stategrid.echarge.wedgit.chart; public class PointBean { private double percentX; private double percentY; private int numX; private int numY; public PointBean() { } public PointBean(double percentX, double percentY) { this.percentX = percentX; this.percentY = percentY; } public PointBean(double percentX, double percentY, int numY) { this.percentX = percentX; this.percentY = percentY; this.numY = numY; } public PointBean(double percentX, double percentY, int numX, int numY) { this.percentX = percentX; this.percentY = percentY; this.numX = numX; this.numY = numY; } public double getPercentX() { return percentX; } public void setPercentX(double percentX) { this.percentX = percentX; } public double getPercentY() { return percentY; } public void setPercentY(double percentY) { this.percentY = percentY; } public int getNumY() { return numY; } public void setNumY(int numY) { this.numY = numY; } public int getNumX() { return numX; } public void setNumX(int numX) { this.numX = numX; } }