自定义控件的实现有三种方式,分别是:组合控件、继承控件和自绘控件
一:组合控件
1:新建一个Android项目,创建自定义的布局文件add_delete.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/del"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="-" />
<EditText
android:id="@+id/ed_number"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:layout_height="wrap_content" />
<Button
android:id="@+id/add"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="+" />
</LinearLayout>
2:创建AddDelete类,继承RelativeLayout
本页面中主要是为自定义的标题栏加载了布局,为按钮添加事件监听方法,获取与修改EditText的方法
public class AddDelete extends RelativeLayout{
private OnAddDeleteClickListener listener;
private EditText ed_number;
//对外提供一个点击的回调接口
interface OnAddDeleteClickListener{
void onAddClick(View v);
void onDelClick(View v);
}
public void setOnAddDeleteClick(OnAddDeleteClickListener listener){
this.listener = listener;
}
public AddDelete(Context context) {
this(context,null);
}
public AddDelete(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public AddDelete(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
intiView(context, attrs, defStyleAttr);
}
private void intiView(Context context, AttributeSet attrs, int defStyleAttr) {
View.inflate(context,R.layout.adddelete,this);
TextView add = (TextView)findViewById(R.id.add);
TextView del = (TextView)findViewById(R.id.del);
ed_number = (EditText) findViewById(R.id.ed_number);
add.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
listener.onAddClick(view);
}
});
del.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
listener.onDelClick(view);
}
});
}
//对外提供设置EditText值的方法
public void setNumber(int number){
//若果设置的值小于0则不设置
if (number > 0) {
ed_number.setText(number + "");
}
}
//得到控件原来的值,并转成int类型
public int getNumber(){
int number = 0;
try {
//把值强转成int类型
number = Integer.valueOf(ed_number.getText().toString().trim());
}catch (Exception e){
number = 0;
}
return number;
}
}
3:在activity_main.xml中引入自定义的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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="activity.example.com.view.MainActivity">
<activity.example.com.view.AddDelete
android:id="@+id/ad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></activity.example.com.view.AddDelete>
</RelativeLayout>
4:MainActivity类
public class MainActivity extends AppCompatActivity { private AddDelete ad; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获取id ad = (AddDelete)findViewById(R.id.ad); //两个按钮的点击事件 ad.setOnAddDeleteClick(new AddDelete.OnAddDeleteClickListener() { //增加EditText的值 @Override public void onAddClick(View v) { int number = ad.getNumber(); number++; ad.setNumber(number); } //减少EditText的值 @Override public void onDelClick(View v) { int number = ad.getNumber(); number--; ad.setNumber(number); } }); } }
二:继承控件1:main_activity布局文件中写<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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="activity.example.com.view.MainActivity"> <activity.example.com.view.MButton android:layout_width="match_parent" android:layout_height="wrap_content" android:text="自定义的button"" /> </RelativeLayout>
2:创建MButton类,继承Button3:自绘控件public class MButton extends Button{ public MButton(Context context) { this(context,null); } public MButton(Context context, AttributeSet attrs) { this(context, attrs,0); } public MButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } private void initView() { //为button设置背景颜色 setBackgroundColor(Color.parseColor("#FF0000")); } }
自绘控件的内容都是自己绘制出来的,在View的onDraw方法中完成绘制1:main_activity布局文件中写<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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="activity.example.com.view.MainActivity"> <activity.example.com.view.MyView android:layout_width="100dp" android:layout_height="100dp" android:background="@color/colorAccent"/> </RelativeLayout>
2:创建MyView类,继承View
public class MyView extends View{ public MyView(Context context) { super(context); } public MyView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } //自绘控件的内容都是自己绘制出来的,在View的onDraw方法中完成绘制,是最重要的方法 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int height = getHeight(); // 绘图范围 int react = Math.min(width, height); // 半径 int radius = react / 2; // 绘制最外层的大圆 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.BLACK); paint.setAntiAlias(true);//消除锯齿 paint.setStyle(Paint.Style.STROKE); canvas.drawCircle(radius, radius, radius, paint); // 画扇形 paint.reset(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(20); paint.setColor(Color.GREEN); RectF rectF = new RectF(); paint.setAntiAlias(true);//消除锯齿 rectF.set(10, 10, react-10, react-10); canvas.drawArc(rectF, -90, progress*360/100, true, paint); // 画内层的小圆 paint.reset(); paint.setColor(Color.WHITE); paint.setAntiAlias(true);//消除锯齿 paint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.drawCircle(radius, radius, radius-20, paint); // 画进度文字 paint.reset(); paint.setColor(Color.BLUE); paint.setTextSize(40); Rect rect = new Rect(); paint.getTextBounds(progress + "", 0, String.valueOf(progress).length(), rect); int textWidth = rect.width(); int textHeight = rect.height(); canvas.drawText(progress + "", radius-textWidth/2, radius-textHeight/2, paint); } }
四:设置自定义view的属性1:首先在values文件夹下创建attrs.xml<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="Style"> <attr name="left" format="string"></attr> <attr name="middle" format="string"></attr> <attr name="right" format="string"></attr> <attr name="color" format="color"></attr> </declare-styleable> </resources>
2:创建的类中//R.styleable.上面declare-styleable标签的nameTypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.Style); String left = typedArray.getString(R.styleable.Style_left); String middle = typedArray.getString(R.styleable.Style_middle); String right = typedArray.getString(R.styleable.Style_right); int color = typedArray.getColor(R.styleable.Style_color, Color.RED); 控件id.setText(left); 控件id.setText(middle); 控件id.setText(right); 控件id.setTextColor(color); //回收 typedArray.recycle();
3:main_activity布局文件中写<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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="activity.example.com.view.MainActivity"> <activity.example.com.view.AddDelete android:id="@+id/ad" android:layout_width="wrap_content" android:layout_height="wrap_content" app:left="减" app:middle="2" app:right="加" app:color="#0000FF" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true"></activity.example.com.view.AddDelete> </RelativeLayout>