目录
五、自定义控件:
六、自定义控件主题theme、样式Style:
1.主题和样式
2.使用主题
3.使用样式
清单文件中使用主题:
布局文件中使用样式:
//自定义控件之滑动移位小方快
本文章作为学习总结
尊重原创老师 参考部分前辈网络总结,如涉及版权问题,请联系。
五、自定义控件:
1.使用自定义控件,必须在布局文件中添加schemas声明,xmlns:app=http://schemas.android.com/apk/res-auto,
2.......
六、自定义控件主题theme、样式Style:
1.主题和样式
2.主题和样式的定义方法类似,都是在
2.使用主题
a)从AndroidManifest中指定,可以选择Application应用级:
或是Activity级:
b)从Java代码中指定:
public void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.MyTheme);
setContentView(R.layout.main); }
3.使用样式
a)从layout的xml文件中指定:
android:layout_width="fill_parent"
android:layout_height="wrap_content">
b)从Java代码中指定:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.MyTheme);
setContentView(R.layout.main);
LinearLayout ll = (LinearLayout)findViewById(R.id.llMain);
EditText et = new EditText(this, null, R.attr.myStyle);
ll.addView(et); }
清单文件中使用主题:
(1)系统主题:android:theme=”@android:style/ButtonBar”
(2)自定义主题:android:theme=”@style/MyStyle”
布局文件中使用样式:
(1)系统样式:style=”@android:style/ButtonBar”
(2)自定义样式:style=”@style/ChildMyStyle”
上面都提到自定义主题,那么现在需要定制自己的主题,步骤:
(1)打开目录res/values下的styles.xml文件;
(2)添加resources的子标签:
- #00ff00
说明:属性name指定名称ChildMyTheme,parent表示继承MyTheme的所有样式,改样式可以自定义也可以是系统的。item标签指定当前style/theme的样式,主题
item的那么属性值一定是与系统相符合的,比如字体颜色:
- #0000ff
。
//自定义控件之滑动移位小方快
package com.example.text1;
//自定义控件之滑动移位小方快
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.RegionIterator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Scroller;
import androidx.annotation.Nullable;
public class SlideControl2 extends View {
private int VIEW_HEIGHT;
//滑动大方快的初始变量定义
private int strokeLineColor_int;
private int strokeCheckedSolidColor_int;
private int strokeNoCheckedSolidColor_int;
private int squareCheckedColor_int;
private int squareNoCheckedColor_int;
//
private int squareChecked_int;
private int squareStrokeColor_int;
//当前按钮的开关状态
private boolean isChecked = false;
//圆的x轴圆心
private float circle_x;
private float circleEndX;
private float circleStartX;
private Paint mPaint;
private Scroller mScroller;
//边框矩形边框颜色
private String StrokeLineColor = "#bebfc1";
//边框矩形填充颜色
private String StrokeSolidColor = "#00ffffff";
//方块边框颜色
private String SquareStrokeColor = "#abacaf";
//方块checked填充颜色
private String SquareCheckedColor = "#36648B";
//方块非checked填充颜色
private String SquareNoCheckedColor = "#668B8B";
// private String SquareNoCheckedColor = "#bebfc1";
private int view_height_int;
private int mWidth;
private int mHeight;
//控件内边距
private static int PADDING = 20;
//移动的判定距离
private static int MOVE_DISTANCE = 50;
//边框矩形的高
private int strokeHeight;
//边框矩形的半径
private float strokeSquareRadius;
private int centerY;
private int centerX;
//内部Square方块的半径
private float squareRadius;
//椭圆的边框宽度
private static final int strokeLineWidth = 3;
//圆的边框宽度
private static final int squareStrokeWidth = 3;
private float preX = 0;
private boolean isMove;
//状态改变监听
public interface SlideControlOnCheckedListener {
void onCheckedChangeListener(boolean isChecked);
}
private SlideControlOnCheckedListener mListener;
public SlideControl2(Context context) {
super(context);
init(context);
}
public SlideControl2(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SlideControl2(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
//是否是大方块 初始状态false
private boolean isBigSquare = false;
public void setBigSquareModel(int strokeLineColor, int strokeCheckedSolidColor,
int strokeNoCheckedSoliderColor, int squareCheckedColor,
int squareNoCheckedColor) {
isBigSquare = true;
strokeLineColor_int = strokeLineColor;
strokeCheckedSolidColor_int = strokeCheckedSolidColor;
strokeNoCheckedSolidColor_int = squareNoCheckedColor;
squareCheckedColor_int = squareCheckedColor;
squareNoCheckedColor_int = squareNoCheckedColor;
invalidate();
}
public void setOnCheckedListener(SlideControlOnCheckedListener listener) {
this.mListener = listener;
}
public void setChecked(boolean checked) {
this.isChecked = checked;
if (isChecked) {
circle_x = circleEndX;
} else {
circle_x = circleStartX;
}
invalidate();
}
private void init(Context context) {
setEnabled(true);
setClickable(true);
mPaint = new Paint();
mScroller = new Scroller(context);
view_height_int = dip2px(context, VIEW_HEIGHT);
strokeLineColor_int = Color.parseColor(StrokeLineColor);
strokeNoCheckedSolidColor_int = Color.parseColor(StrokeSolidColor);
squareStrokeColor_int = Color.parseColor(SquareStrokeColor);
squareChecked_int = Color.parseColor(SquareCheckedColor);
squareNoCheckedColor_int = Color.parseColor(SquareNoCheckedColor);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//a.当控件的layout_width或layout_height指定为wrap_content时,为AT_MOST
//b.当控件的layout_width或layout_height指定为match_parent或具体数值时,为EXACTLY
//处理wrap-content
if (heightMode == MeasureSpec.AT_MOST) {
//如果是wrap_content
heightSize = view_height_int;
}
if (widthMode == MeasureSpec.AT_MOST) {
widthSize = heightSize * 2;
}
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
if (isBigSquare) {
PADDING = h / 10;
;
} else {
PADDING = h / 15;
}
MOVE_DISTANCE = mWidth / 100;
//边框矩形的高
strokeHeight = h - PADDING * 2;
//边框矩形的半径
strokeSquareRadius = strokeHeight / 2;
centerY = mHeight / 2;
//内部方块的半径
if (isBigSquare) {
squareRadius = strokeSquareRadius + PADDING;
} else {
squareRadius = strokeSquareRadius - PADDING * 2;
}
Log.i("TAG", "mHeight:" + mHeight + " strokeCircleRadius: " + strokeSquareRadius);
//内部圆的x轴起始坐标
circleStartX = PADDING + strokeSquareRadius;
//内部圆的x轴终点坐标
circleEndX = mWidth - circleStartX;
if (isChecked) {
circle_x = circleEndX;
} else {
circle_x = circleStartX;
}
//控件的中线
centerX = mWidth / 2;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawRect(canvas);
drawSquare(canvas);
}
//画边框矩形
private void drawRect(Canvas canvas) {
mPaint.reset();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
if (isBigSquare && isChecked) {
mPaint.setColor(strokeCheckedSolidColor_int);
} else {
mPaint.setColor(strokeNoCheckedSolidColor_int);
}
//画填充
canvas.drawRoundRect(PADDING, PADDING, mWidth - PADDING, mHeight - PADDING,
strokeSquareRadius, strokeSquareRadius, mPaint);
//画边框
mPaint.setStrokeWidth(strokeLineWidth);
mPaint.setColor(strokeLineColor_int);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawRect(PADDING, PADDING, mWidth - PADDING, mHeight - PADDING, mPaint);
}
//画里面的圆
private void drawSquare(Canvas canvas) {
mPaint.reset();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
float squareRadiusNew = squareRadius;
if (isBigSquare) {
squareRadiusNew -= squareStrokeWidth;
}
if (isChecked) {
mPaint.setColor(squareChecked_int);
} else {
mPaint.setColor(squareNoCheckedColor_int);
}
// canvas.drawRect(PADDING, PADDING, mWidth - PADDING, (mHeight - PADDING) / 2, mPaint);
// canvas.drawRoundRect(circle_x, circle_x * 2, (mWidth - circle_x), (mHeight - circle_x) / 8,
// strokeSquareRadius, strokeSquareRadius, mPaint);
// canvas.drawRect(circle_x, circle_x * 2, (mWidth - circle_x), (mHeight - circle_x) / 8, mPaint);//滑动变换颜色方块
canvas.drawRect(circle_x - centerY + PADDING, PADDING, circle_x * 2, centerY * 2 - PADDING, mPaint);//十分正确的滑动移位小方块
// canvas.drawCircle(circle_x, centerY, squareRadiusNew, mPaint);//滑动移位小圆
// if (isBigSquare) {
// //画圆的边
// mPaint.setColor(squareStrokeColor_int);
// mPaint.setStyle(Paint.Style.STROKE);
// mPaint.setStrokeWidth(squareStrokeWidth);
// canvas.drawCircle(circle_x, centerY, squareRadiusNew, mPaint);
// }
// Rect rect1 = new Rect(PADDING * 2, PADDING * 2, (mWidth - PADDING) , (mHeight - PADDING) / 2);
// Rect rect1 = new Rect(PADDING * 2, PADDING * 2, centerY - PADDING , centerY - PADDING);
//背景颜色
// canvas.drawARGB(255, 139, 197, 186);
// mPaint.setColor(0xff36648B);
// mPaint.setStyle(Paint.Style.FILL);
// mPaint.setStrokeWidth(10);
//
// canvas.drawRect(rect1, mPaint);
//
//
// //构造两个区域
// Region region1 = new Region(rect1);
//
//
// //构造一个填充画笔,将所选的区域用草绿色填充
// Paint paint_fill = new Paint();
// paint_fill.setColor(0xff668B8B);
// paint_fill.setStyle(Paint.Style.FILL);
// drawRegion(canvas, region1, paint_fill);
}
// //定义drawRegion()函数,将整个Region画出来
// private void drawRegion(Canvas canvas, Region region1, Paint paint) {
// RegionIterator iter = new RegionIterator(region1);
// Rect r = new Rect();
// while (iter.next(r)) {
// canvas.drawRect(r, paint);
// }
// }
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
preX = event.getX();
isMove = false;
if (!isChecked) {
circle_x = PADDING + strokeSquareRadius;
} else {
circle_x = mWidth - PADDING - strokeSquareRadius;
}
break;
case MotionEvent.ACTION_MOVE:
float move_x = event.getX();
if (Math.abs(move_x - preX) > MOVE_DISTANCE) {
isMove = true;
if (move_x < circleStartX) {
circle_x = circleStartX;
isChecked = false;
} else if (move_x > circleEndX) {
circle_x = circleEndX;
isChecked = true;
} else {
circle_x = move_x;
}
invalidate();
}
break;
case MotionEvent.ACTION_UP:
if (isMove) {
//滑过中控线
if (circle_x >= centerX) {
//关闭(执行开启)
//源码:1000ms内滑向destX,效果就是慢慢滑动---scrollX起点横坐标,delta终点横坐标,1000ms时间
//mScroller.startScroll(scrollX,0,delta,0,1000)
mScroller.startScroll((int) circle_x, 0, (int) (circleEndX - circle_x), 0);
isChecked = true;
} else {
//开启(执行关闭)
mScroller.startScroll((int) circle_x, 0, (int) (circleStartX - circle_x), 0);
isChecked = false;
}
} else {
//没有滑过中控线
if (!isChecked) {
//关闭(执行开启)
mScroller.startScroll((int) circle_x, 0, (int) (circleEndX - circle_x), 0);
isChecked = true;
} else {
//开启(执行关闭)
mScroller.startScroll((int) circle_x, 0, (int) (circleStartX - circle_x), 0);
isChecked = false;
}
}
if (mListener != null) {
mListener.onCheckedChangeListener(isChecked);
}
invalidate();
break;
}
return super.onTouchEvent(event);
}
//实现弹性滑动--固定代码
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
circle_x = mScroller.getCurrX();
invalidate();
}
}
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}