一、目的
写代码实现一个画板效果。
二、知识点
一、横竖屏切换设置:
1.配置文件:
screenOrientation= | 意义 |
---|---|
"sensor" | 随着屏幕的方向变化而变化 |
"portrait" | 竖屏锁定 |
"landscape" | 锁定横屏(一个方向)sensorLandscape 2个方向 |
2.代码设置:onResume里设置
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULLSENSOR);
二、自适应布局
整体:ConstraintLayout约束布局:要约束确定的宽高,xy
部件:LinearLayout
三、自定义滑动条Slider
1.进度条;没有thumb小圆点,不接收触摸
2.滑动条:有小圆点,接收触摸
1.当触摸时小圆点放大
2.监听滑动事件
3.横竖切换:width>height横着 width>height 竖着
创建Slider extends View
1.添加约束
<com.example.a16palette.Slider
android:layout_width="20dp"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"/>
进度条背景
进度条小圆点
四、滑动
五、外部
样式:进度条 or 滑动条选择
进度值的交互及在MainActivity里的模拟及max值的设置
六、数据回调
改正:MotionEvent.ACTION_DOWN处不需要条件的判断
三、实际应用
今日实现的最终效果:
完整代码:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@+id/operation"
app:layout_constraintTop_toTopOf="parent">
<!--滑动条-->
<com.example.a16palette.Slider
android:id="@+id/slider"
android:layout_width="20dp"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/operation"
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/colorAccent">
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Slider.java(自己创的一个Class用来自定义滑动条的):有点多,别怕
package com.example.a16palette;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
public class Slider extends View {
private int lineSize = 4;//线的粗细
private Paint linePaint;//线画笔
private int lineColor = Color.GRAY;//默认线颜色灰色
private int centerX;//中心点x
private int centerY;//中心点y
private int radius;//小圆点的半径
private Paint circlePaint;//画圆的画笔
private int thumbColor = Color.MAGENTA;//圆点的颜色
private int thumbScale = 4;//小圆点缩放倍数分之一
private float position;//记录触摸点的坐标变化值
private Paint progressPaint;//进度条进度的画笔
private int progressColor = Color.MAGENTA;//进度条颜色
public static int PROGRESS = 0;//进度条
public static int SLIDER = 1;//滑动条
private int style = PROGRESS;//样式:进度条或滑动条
public int max = 100;//设置最大值 默认100
public float progress;//进度值
private OnSliderChangeListener onSliderChangeListener;//滑动改变的监听者
public Slider(Context context) {
super(context);
init();
}
public Slider(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
// setBackgroundColor(Color.BLACK);
linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
linePaint.setColor(lineColor);
linePaint.setStrokeWidth(lineSize);
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(thumbColor);
circlePaint.setStyle(Paint.Style.FILL);
progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
progressPaint.setColor(progressColor);
progressPaint.setStrokeWidth(lineSize);
}
@Override
protected void onDraw(Canvas canvas) {
if (getWidth() > getHeight()){
//横着
canvas.drawLine(0,getHeight()/2,getWidth(),getHeight()/2,linePaint);//进度条打底
canvas.drawLine(0,getHeight()/2,position,getHeight()/2,progressPaint);//进度条
radius = getHeight()/thumbScale;
//X的变化
if (position < radius){
centerX = radius;
}else if (position > getWidth() - radius){
centerX = getWidth() - radius;
}
else {
centerX = (int) position;
}
centerY = getHeight()/2;
// centerY =getPivotY();
}else {
//竖着
canvas.drawLine(getWidth()/2,0,getWidth()/2,getHeight(),linePaint);//进度条打底
if (position > 0) {
canvas.drawLine(getWidth() / 2, 0, getWidth() / 2, position, progressPaint);//进度条
}
radius = getWidth()/thumbScale;
centerX = getWidth()/2;
//Y的变化
if (position < radius){
centerY = radius;
}else if (position > getHeight() - radius){
centerY = getHeight() - radius;
}else {
centerY = (int) position;
}
}
// //画进度条
// canvas.drawLine();
//画小圆点
if (style == SLIDER) {
canvas.drawCircle(centerX, centerY, radius, circlePaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//小圆点放大
thumbScale = 2;
if(getHeight()<getWidth()){
//横 X变化
position = event.getX();
if(position < 0) position =0;//避免点到进度条外面仍有x,y值
else if(position > getWidth()) position =getWidth();
}else {
//竖 Y变化
position = event.getY();
if(position < 0) position =0;
else if(position > getHeight()) position =getHeight();
}
callback();
break;
case MotionEvent.ACTION_MOVE:
//获取当前触摸点的值 XorY
if(getHeight()<getWidth()){
//横 X变化
position = event.getX();
if(position < 0) position =0;
else if(position > getWidth()) position =getWidth();
}else {
//竖 Y变化
position = event.getY();
if(position < 0) position =0;
else if(position > getHeight()) position =getHeight();
}
callback();
break;
case MotionEvent.ACTION_UP:
//小圆点恢复
thumbScale = 4;
break;
}
if (style == SLIDER) {
invalidate();//“刷新”
}
return true;//这样就不会继续往下传了
}
//监听
private void callback(){
if(onSliderChangeListener != null){
// onSliderChangeListener.progressChanged(progress * max);//和position/getWidth(横)getHeight(竖)
if (getWidth() > getHeight()) {
progress = position / getWidth();
} else {
progress = position / getHeight();
}
onSliderChangeListener.progressChanged(progress * max);
}
}
public int getStyle() {
return style;
}
public void setStyle(int style) {
this.style = style;
}
public float getProgress() {
return progress;
}
public void setProgress(float progress) {
this.progress = progress;
if (progress < 1.0001) {
//将进度值转换为控件中的尺寸位置
if (getWidth() > getHeight()) {//横
position = progress * getWidth();
} else position = progress * getHeight();
invalidate();//
}
}
public void setMax(int max) {
this.max = max;
}
public void setOnSliderChangeListener(OnSliderChangeListener onSliderChangeListener) {
this.onSliderChangeListener = onSliderChangeListener;
}
//实现回调数据给外部
public interface OnSliderChangeListener{
void progressChanged(float progress);
}
}
MainActivity.java:
package com.example.a16palette;
import androidx.appcompat.app.AppCompatActivity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.widget.SeekBar;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Slider slider = findViewById(R.id.slider);
slider.setMax(50);
slider.setStyle(Slider.SLIDER);//只设置这个时(无下面那)小圆点也会出来
// //定时器 模拟进度
// new Timer().schedule(new TimerTask() {
// @Override
// public void run() {
// slider.setProgress((float)(slider.getProgress()+0.01));
// }
// },0,100);
slider.setOnSliderChangeListener(new Slider.OnSliderChangeListener() {
@Override
public void progressChanged(float progress) {
System.out.println(""+progress);
}
});
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
//设置横竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
四、心得
学了这么久,唯一很明显的变化就是现在打代码的速度快了不少,但是要让自己变思考边自己写还是不太行,希望不久我的手速赶不上想的速度。