平面设计软件下载网站/如何制作微信小程序
控件选择顺序:原生,开源,自定义控件
今天做一个类似于股票走势图的控件,效果图:
首先先了解下自定义控件的执行流程
新建CustomView
CustomView
//继承View或View的子类,就是自定义控件
public class CustomView extends View {int viewHeight;int viewWidth;//AttributeSet对应布局中的属性public CustomView(Context context, AttributeSet attrs) {super(context, attrs);}//得到控件大小@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {viewWidth = w;viewHeight = h;super.onSizeChanged(w, h, oldw, oldh);}//canvas画文字,图形@Overrideprotected void onDraw(Canvas canvas) {Paint paint = new Paint();paint.setColor(Color.BLACK);Rect rect = new Rect(0,0,viewWidth,viewHeight);canvas.drawRect(rect,paint);}@Overridepublic boolean onTouchEvent(MotionEvent event) {return super.onTouchEvent(event);}}
MainActivity
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}
}
activity_main
<com.xx.myapplication.CustomViewandroid:layout_width="match_parent"android:layout_height="match_parent"/>
第一次执行流程
MainActivity中onCreate中的setContentView执行后
执行自定义控件的构造方法
onSizeChanged
onDraw
如果单击,触发onTouchEvent
如果横竖屏发生变化
会重新执行MainActivity的onCreate
执行自定义控件的构造方法
onSizeChanged
onDraw
如果AndroidManifest中设置configChanges
android:configChanges="orientation|screenSize|keyboardHidden"
再次执行程序,第一次执行流程还是相同的
如果横竖屏发生变化,会直接再次执行
onSizeChanged
onDraw
现在我们绘制底部的数字
CustomView
//继承View或View的子类,就是自定义控件
public class CustomView extends View {int viewHeight;int viewWidth;private ArrayList<HashMap<String, String>> list;int timeGap;//时间间隙public void setData(ArrayList<HashMap<String,String>> list){this.list = list;}//AttributeSet对应布局中的属性public CustomView(Context context, AttributeSet attrs) {super(context, attrs);}//得到控件大小@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {viewWidth = w;viewHeight = h;super.onSizeChanged(w, h, oldw, oldh);}//canvas画文字,图形@Overrideprotected void onDraw(Canvas canvas) {Paint paint = new Paint();paint.setColor(Color.BLACK);Rect rect = new Rect(0,0,viewWidth,viewHeight);canvas.drawRect(rect,paint);//画时间paint.setColor(Color.WHITE);paint.setTextSize(24);//用代码得最后的时间文字的宽度String lastTime = list.get(list.size() - 1).get("time");Rect sizeRect = new Rect();//矩形大小就是文字的大小paint.getTextBounds(lastTime,0,lastTime.length(),sizeRect);int lastTimeWidth = sizeRect.width();timeGap = (viewWidth-lastTimeWidth)/(list.size()-1);for(int i=0;i<list.size();i++){HashMap<String,String> hashMap = list.get(i);String time = hashMap.get("time");int timeX = i*timeGap;//画文字的时候,y在文字的下面int timeY = viewHeight;canvas.drawText(time,timeX,timeY,paint);}}@Overridepublic boolean onTouchEvent(MotionEvent event) {return super.onTouchEvent(event);}}
MainActivity
public class MainActivity extends AppCompatActivity {private CustomView customView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);customView = findViewById(R.id.customView);customView.setData(getData());}public ArrayList<HashMap<String,String>> getData(){ArrayList<HashMap<String,String>> list = new ArrayList<>();HashMap<String,String> map = new HashMap<>();map.put("time","9");map.put("price","3200");list.add(map);map = new HashMap<>();map.put("time","10");map.put("price","5000");list.add(map);map = new HashMap<>();map.put("time","11");map.put("price","8000");list.add(map);map = new HashMap<>();map.put("time","13");map.put("price","7800");list.add(map);return list;}
}
画价格
//继承View或View的子类,就是自定义控件
public class CustomView extends View {......int maxPrice;//最大价格public void setData(ArrayList<HashMap<String,String>> list){this.list = list;//计算最大价格for(int i=0;i<list.size();i++){int currentPrice = Integer.parseInt(list.get(i).get("price"));if(currentPrice > maxPrice){maxPrice = currentPrice;}}}......//canvas画文字,图形@Overrideprotected void onDraw(Canvas canvas) {.....//价格高度 = 视图高度 - 文字高度int priceHeight = viewHeight -sizeRect.height();timeGap = (viewWidth-lastTimeWidth)/(list.size()-1);for(int i=0;i<list.size();i++){HashMap<String,String> hashMap = list.get(i);String time = hashMap.get("time");int timeX = i*timeGap;//画文字的时候,y在文字的下面int timeY = viewHeight;canvas.drawText(time,timeX,timeY,paint);//画价格String price = hashMap.get("price");int currentPrice = Integer.parseInt(price);int priceY = currentPrice * priceHeight / maxPrice;//值越大,显示在下面。应该显示在上面priceY = priceHeight - priceY;//最大值 显示在控件外面priceY = priceY + sizeRect.height();canvas.drawText(price,timeX,priceY,paint);}}
......
}
画线
//继承View或View的子类,就是自定义控件
public class CustomView extends View {......//canvas画文字,图形@Overrideprotected void onDraw(Canvas canvas) {......//画时间......for(int i=0;i<list.size();i++){......//画线if(i<list.size()-1){int startX=0,startY=0,stopX=0,stopY=0;startX = timeX;startY = priceY;stopX = (i+1)*timeGap;int nextPrice = Integer.parseInt(list.get(i+1).get("price"));stopY = nextPrice * priceHeight /maxPrice;//倒过来,大的应该显示在上面stopY = priceHeight-stopY;//最大的值可能跑到屏幕外,所以加上文字高度stopY = stopY + sizeRect.height();canvas.drawLine(startX,startY,stopX,stopY,paint);}}}......}
现在把价格改为随机变化的
修改MainActivity
public class MainActivity extends AppCompatActivity {private CustomView customView;Random random = new Random();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);customView = findViewById(R.id.customView);customView.setData(getData());final Handler handler = new Handler();handler.postDelayed(new Runnable() {@Overridepublic void run() {customView.setData(getData());//让android框架去调用ondraw、//间接调用customView.invalidate();handler.postDelayed(this,1000);}},1000);}public ArrayList<HashMap<String,String>> getData(){ArrayList<HashMap<String,String>> list = new ArrayList<>();HashMap<String,String> map = new HashMap<>();map.put("time","9");map.put("price",String.valueOf(random.nextInt(5000)));list.add(map);map = new HashMap<>();map.put("time","10");map.put("price",String.valueOf(random.nextInt(5000)));list.add(map);map = new HashMap<>();map.put("time","11");map.put("price",String.valueOf(random.nextInt(5000)));list.add(map);map = new HashMap<>();map.put("time","13");map.put("price",String.valueOf(random.nextInt(5000)));list.add(map);return list;}
}
现在增加点击画线功能
//继承View或View的子类,就是自定义控件
public class CustomView extends View {......int touchY;//单击的Y坐标......//canvas画文字,图形@Overrideprotected void onDraw(Canvas canvas) {......//画线if(touchY>0){paint.setColor(Color.RED);canvas.drawLine(0,touchY,viewWidth,touchY,paint);}}@Overridepublic boolean onTouchEvent(MotionEvent event) {touchY = (int) event.getY();int x = (int) event.getX();//单击的第几个时间点int index = x/timeGap;Toast.makeText(getContext(),"第"+index+"个,"+list.get(index).get("time"),Toast.LENGTH_SHORT).show();return super.onTouchEvent(event);}}
注意:
绘制文本的时候,参数X,Y并不是绘制的起点,而是文字的底部,这个x,y 是文字的左下角的坐标
demo下载地址
https://download.csdn.net/download/u010356768/11131421