Android實(shí)現(xiàn)玩轉(zhuǎn)畫板功能
實(shí)現(xiàn)步驟:
一、預(yù)期效果

二、設(shè)置橫豎屏切換
| screenOrientation屬性 | ???????作用 |
|---|---|
| user | 用戶當(dāng)前設(shè)置的方向。 |
| unspecified | 由系統(tǒng)選擇顯示方向,不同的設(shè)備可能會有所不同。(旋轉(zhuǎn)手機(jī),界面會跟著旋轉(zhuǎn)) |
| landscape | 限制界面為橫屏,旋轉(zhuǎn)屏幕也不會改變當(dāng)前狀態(tài)。 |
| portrait | 限制界面為豎屏,旋轉(zhuǎn)屏幕也不會改變當(dāng)前狀態(tài)。 |
| behind | 與前一個(gè)activity方向相同。 |
| sensor | 根據(jù)傳感器定位方向,旋轉(zhuǎn)手機(jī)90度,180,270,360,界面都會發(fā)生變化。 |
| nosensor | 不由傳感器確定方向。旋轉(zhuǎn)設(shè)備的時(shí)候,界面不會跟著旋轉(zhuǎn)。初始界面方向由系統(tǒng)提供。 |
| sensorLandscape | (橫屏的旋轉(zhuǎn),不會出現(xiàn)豎屏的現(xiàn)象)根據(jù)傳感器定位方向,旋轉(zhuǎn)手機(jī)180度界面旋轉(zhuǎn)。一般橫屏游戲會是這個(gè)屬性。 |
| sensorPortrait | (豎屏的旋轉(zhuǎn),不會出現(xiàn)橫屏的現(xiàn)象)根據(jù)傳感器定位方向,旋轉(zhuǎn)手機(jī)180度界面會旋轉(zhuǎn)。 |
三、確定布局

<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"><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="0dp"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toTopOf="@id/operation"><!--滑動(dòng)條--><com.example.a16drawboard.Sliderandroid:id="@+id/slider"android:layout_width="20dp"android:layout_height="match_parent"android:layout_marginLeft="20dp"android:layout_marginTop="20dp"android:layout_marginBottom="20dp"app:layout_constraintLeft_toLeftOf="parent"/><!--畫板--><com.example.a16drawboard.DrawBoardViewandroid:id="@+id/board"android:layout_width="0dp"android:layout_height="match_parent"app:layout_constraintLeft_toRightOf="@id/slider"app:layout_constraintRight_toLeftOf="@id/color"/><!--選顏色--><LinearLayoutandroid:id="@+id/color"android:layout_width="60dp"android:layout_height="match_parent"android:orientation="vertical"android:layout_marginRight="20dp"app:layout_constraintRight_toRightOf="parent"android:gravity="center"><Buttonandroid:layout_width="match_parent"android:layout_height="50dp"android:background="@color/colorAccent"android:onClick="choiceColor"/><Buttonandroid:layout_width="match_parent"android:layout_height="50dp"android:background="@color/colorPrimary"android:onClick="choiceColor"/><Buttonandroid:layout_width="match_parent"android:layout_height="50dp"android:background="#f00"android:onClick="choiceColor"/><Buttonandroid:layout_width="match_parent"android:layout_height="50dp"android:background="#000"android:onClick="choiceColor"/></LinearLayout></androidx.constraintlayout.widget.ConstraintLayout><LinearLayoutandroid:id="@+id/operation"android:layout_width="match_parent"android:layout_height="60dp"android:background="#f00"android:orientation="horizontal"app:layout_constraintBottom_toBottomOf="parent"android:gravity="center"><Buttonandroid:layout_width="70dp"android:layout_height="wrap_content"android:text="撤銷"android:onClick="goBack"/><Buttonandroid:layout_width="70dp"android:layout_height="wrap_content"android:text="清空"android:onClick="clear"/><Buttonandroid:layout_width="70dp"android:layout_height="wrap_content"android:text="橡皮擦"android:onClick="eraser"/><Buttonandroid:layout_width="70dp"android:layout_height="wrap_content"android:text="保存"android:onClick="save"/><Buttonandroid:layout_width="70dp"android:layout_height="wrap_content"android:text="上一步"android:onClick="lastStep"/></LinearLayout></androidx.constraintlayout.widget.ConstraintLayout>
四、自定義滑動(dòng)條
public class Slider extends View {private int lineSize = 6; // 線條的粗細(xì)private int lineColor = Color.BLACK;// 默認(rèn)線條顏色private Paint linePaint;private Paint circlePaint; // 圓點(diǎn)畫筆private int thumbColor = Color.MAGENTA; // 圓點(diǎn)顏色private int cx; // 中心點(diǎn)xprivate int cy; // 中心點(diǎn)yprivate int radius; // 小圓點(diǎn)半徑private int thumbScale = 4; // 圓點(diǎn)縮放尺寸private float position; // 觸摸點(diǎn)的坐標(biāo)private Paint progressPaint; // 進(jìn)度條進(jìn)度的畫筆private int progressColor = Color.MAGENTA; // 進(jìn)度條顏色public static int PROGRESS = 0; // 進(jìn)度條public static int SLIDER = 1; // 滑動(dòng)條private int style = PROGRESS; // 用戶選擇的樣式,默認(rèn)為進(jìn)度條public int max = 100; // 設(shè)置最大值public float progress; // 進(jìn)度值private OnSliderChangeListener onSliderChangeListener; // 滑動(dòng)改變監(jiān)聽者public Slider(Context context) {super(context);}public Slider(Context context, AttributeSet attrs) {super(context, attrs);init();}private void init(){// 背景線linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);linePaint.setColor(lineColor);linePaint.setStrokeWidth(lineSize);// 圓點(diǎn)circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);circlePaint.setColor(thumbColor);circlePaint.setStyle(Paint.Style.FILL);// 進(jìn)度條progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);progressPaint.setColor(progressColor);progressPaint.setStrokeWidth(lineSize);}@Overrideprotected void onDraw(Canvas canvas) {if (getWidth() > getHeight()){// 橫著canvas.drawLine(0, getHeight()/2, getWidth(), getHeight()/2, linePaint);if (position>0){canvas.drawLine(0, getHeight()/2, position, getHeight()/2, progressPaint);}radius = getHeight()/thumbScale;cy = getHeight()/2;// 確定cx的值if (position < radius) {cx = radius;}else if (position > getWidth()-radius){cx = getWidth()-radius;}else {cx = (int) position;}}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;cx = getWidth()/2;// 確定中心點(diǎn)cy的值if (position<radius){cy = radius;}else if (position > getHeight()-radius){cy = getHeight()-radius;}else {cy = (int) position;}}// 畫小圓點(diǎn)if (style == SLIDER){canvas.drawCircle(cx,cy,radius,circlePaint);}}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN:// 圓點(diǎn)放大thumbScale = 2;// 點(diǎn)下去就到那個(gè)位置if (getWidth()>getHeight()){// 橫向時(shí),y不變 x改變position = event.getX();}else {// 縱向時(shí),x不變 y改變position = event.getY();}callback();break;case MotionEvent.ACTION_MOVE:// 獲取當(dāng)前觸摸點(diǎn)的值XYif (getWidth()>getHeight()){// 橫向時(shí),y不變 x改變position = event.getX();if (position<0){progress = 0;}else if (position>getWidth()){position = getWidth();}}else {// 豎著時(shí),x不變 y改變position = event.getY();if (position<0){progress = 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){if (getWidth()>getHeight()){progress = position/getWidth();}else {progress = position/getHeight();}onSliderChangeListener.progressChange(progress*max);}}public int getStyle() {return style;}public void setStyle(int style) {this.style = style;}public float getProgress() {return progress;}public void setProgress(int progress){// 計(jì)算比例float rate = (float)(progress*1.0/max);setProgress(rate);}public void setProgress(float progress) {this.progress = progress;if (progress <1.001) {// 將進(jìn)度值轉(zhuǎn)化為控件中的尺寸位置if (getWidth() > getHeight()) {position = progress * getWidth();} else {position = progress * getHeight();}invalidate();}}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {if (getWidth() > getHeight()) {position = progress * getWidth();} else {position = progress * getHeight();}}public void setMax(int max) {this.max = max;}public interface OnSliderChangeListener{void progressChange(float progress);}public void setOnSliderChangeListener(OnSliderChangeListener onSliderChangeListener) {this.onSliderChangeListener = onSliderChangeListener;}}
五、繪畫區(qū)域
public class DrawBoardView extends View {private ArrayList<Graph> graphs; // 操作數(shù)組private ArrayList<Graph> orginalGraphs; // 原始數(shù)組private int lineColor = Color.BLACK;private int lineSize = 5;Path mPath;public DrawBoardView(Context context) {super(context);}public DrawBoardView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init();}private void init(){// 初始化數(shù)組graphs = new ArrayList<>();orginalGraphs = new ArrayList<>();setBackgroundColor(Color.WHITE);}@Overrideprotected void onDraw(Canvas canvas) {// 遍歷數(shù)組Iterator<Graph> iterator = graphs.iterator();while (iterator.hasNext()){// 從集合中獲取一個(gè)圖形對象Graph line = iterator.next();// 繪制圖形canvas.drawPath(line.path,line.paint);}}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN:// 創(chuàng)建這條線對應(yīng)的paint和pathPaint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setColor(lineColor);mPaint.setStrokeWidth(lineSize);mPaint.setStyle(Paint.Style.STROKE);mPath = new Path();// 設(shè)置圖形的起點(diǎn)mPath.moveTo(event.getX(),event.getY());// 保存當(dāng)前這個(gè)圖形的詳細(xì)信息Graph temp = new Graph(mPaint,mPath);graphs.add(temp);orginalGraphs.add(temp);break;case MotionEvent.ACTION_MOVE:// 連接從path終點(diǎn)到當(dāng)前觸摸點(diǎn)的線mPath.lineTo(event.getX(),event.getY());break;case MotionEvent.ACTION_UP:break;}invalidate();return true;}// 用私有類來管理圖形的畫筆和路徑private class Graph{Paint paint;Path path;public Graph(Paint paint,Path path){this.paint=paint;this.path=path;}}// 刪除最后一個(gè)圖形 撤銷public void removeLast(){if (graphs.size() >0){graphs.remove(graphs.size()-1);invalidate();}}// 刪除所有 清空public void removeAll(){graphs.clear();invalidate();}// 還原上一步public void returnToLastStep(){// 判斷緩存中是否有if (graphs.size() < orginalGraphs.size()){// 獲取上一步的索引值int index = graphs.size()-1+1;// 從緩存中獲取index,添加到操作數(shù)組中graphs.add(orginalGraphs.get(index));invalidate();}}public int getLineSize() {return lineSize;}public void setLineSize(int lineSize) {this.lineSize = lineSize;}public int getLineColor() {return lineColor;}public void setLineColor(int lineColor) {this.lineColor = lineColor;}}
六、MainActivity
public class MainActivity extends AppCompatActivity {private DrawBoardView boardView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 獲取畫板對象boardView = findViewById(R.id.board);// 獲取滑動(dòng)條對象final Slider slider = findViewById(R.id.slider);slider.setStyle(Slider.SLIDER);slider.setMax(30);slider.setOnSliderChangeListener(new Slider.OnSliderChangeListener() {@Overridepublic void progressChange(float progress) {boardView.setLineSize((int) progress);}});slider.setProgress(boardView.getLineSize());}@Overridepublic void onWindowFocusChanged(boolean hasFocus) {super.onWindowFocusChanged(hasFocus);}@Overrideprotected void onStart() {super.onStart();}@Overrideprotected void onResume() {super.onResume();// 設(shè)置橫屏setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);}@Overrideprotected void onPause() {super.onPause();}@Overrideprotected void onStop() {super.onStop();}// 選擇顏色 獲取按鈕上面的背景顏色public void choiceColor(View view) {// 獲取按鈕上面的背景顏色ColorDrawable drawable = (ColorDrawable) view.getBackground();// 獲取顏色boardView.setLineColor(drawable.getColor());}// 撤回public void goBack(View view) {boardView.removeLast();}// 清空public void clear(View view) {boardView.removeAll();}// 橡皮擦public void eraser(View view) {// 獲取畫板的drawableColorDrawable drawable = (ColorDrawable) boardView.getBackground();// 設(shè)置線條顏色和背景色相同if (drawable != null){boardView.setLineColor(drawable.getColor());}else {boardView.setLineColor(Color.TRANSPARENT);}}// 保存public void save(View view) {}// 還原public void lastStep(View view) {boardView.returnToLastStep();}}
評論
圖片
表情
