(一)组合控件
组合控件,顾名思义就是将一些小的控件组合起来形成一个新的控件,这些小的控件多是系统自带的控件。比如很多应用中普遍使用的标题栏控件,其实用的就是组合控件,那么下面将通过实现一个简单的标题栏自定义控件来说说组合控件的用法。
1、新建一个Android项目,创建自定义标题栏的布局文件title.xml:
import android.content.Context;
import android.graphics.Paint;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
public class Myview extends FrameLayout {
Paint paint ;
private Button leftButton;
private TextView titleText;
//构造器二个参数
public Myview(@NonNull final Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
//加载布局
LayoutInflater.from(context).inflate(R.layout.title, this);
//获得布局中的控件
titleText = (TextView) findViewById(R.id.title_text);
leftButton = (Button) findViewById(R.id.button_left);
}
//为button添加自定义点击事件
public void setLeftButtonlisetener(OnClickListener listener){
leftButton.setOnClickListener(listener);
}
//设置标题的方法
public void setTitleText(String title){
titleText.setText(title);
}
}
Myview mv;
//控件Id
mv = (Myview) findViewById(R.id.mv);
//给布局中Back控件调用 点击事件
mv.setLeftButtonlisetener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "你点击了返回", Toast.LENGTH_SHORT).show();
//关闭的
// finish();
}
});
//给标题添加命名
mv.setTitleText("信息文化博爱");
}
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
public class CounterView extends View implements View.OnClickListener{
// 定义画笔
private Paint mPaint;
// 用于获取文字的宽和高
private Rect mBounds;
// 计数值,每点击一次本控件,其值增加1
private int mcount;
public void init(){
// 初始化画笔、Rect
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBounds = new Rect();
// 本控件的点击事件
setOnClickListener(this);
}
public CounterView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
//在构造其中调用init()画笔
init();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(Color.BLACK);
//绘制一个填充为蓝色的矩形
canvas.drawRect(0,0,getWidth(),getHeight(),mPaint);
mPaint.setColor(Color.YELLOW);
mPaint.setTextSize(50);
String text = String.valueOf(mcount);
//获取文字的宽度个高度
mPaint.getTextBounds(text,0,text.length(),mBounds);
float textwigth=mBounds.width();
float textheight=mBounds.height();
//绘制字符串
canvas.drawText(text,getWidth()/2 - textwigth/2,getHeight()/2
+textheight /2,mPaint);
}
@Override
public void onClick(View v) {
mcount ++;
//重汇
invalidate();
}
}
就是继承已有的控件,创建新控件,保留继承的父控件的特性,并且还可以引入新特性。下面就以支持横向滑动删除列表项的自定义ListView的实现来介绍。
1、创建删除按钮布局delete_btn.xml,这个布局是在横向滑动列表项后显示的:
public class CustomListView extends ListView implements OnTouchListener,
OnGestureListener {
// 手势动作探测器
private GestureDetector mGestureDetector;
// 删除事件监听器
public interface OnDeleteListener {
void onDelete(int index);
}
private OnDeleteListener mOnDeleteListener;
// 删除按钮
private View mDeleteBtn;
// 列表项布局
private ViewGroup mItemLayout;
// 选择的列表项
private int mSelectedItem;
// 当前删除按钮是否显示出来了
private boolean isDeleteShown;
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
// 创建手势监听器对象
mGestureDetector = new GestureDetector(getContext(), this);
// 监听onTouch事件
setOnTouchListener(this);
}
// 设置删除监听事件
public void setOnDeleteListener(OnDeleteListener listener) {
mOnDeleteListener = listener;
}
// 触摸监听事件
@Override
public boolean onTouch(View v, MotionEvent event) {
if (isDeleteShown) {
hideDelete();
return false;
} else {
return mGestureDetector.onTouchEvent(event);
}
}
@Override
public boolean onDown(MotionEvent e) {
if (!isDeleteShown) {
mSelectedItem = pointToPosition((int) e.getX(), (int) e.getY());
}
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// 如果当前删除按钮没有显示出来,并且x方向滑动的速度大于y方向的滑动速度
if (!isDeleteShown && Math.abs(velocityX) > Math.abs(velocityY)) {
mDeleteBtn = LayoutInflater.from(getContext()).inflate(
R.layout.delete_btn, null);
mDeleteBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mItemLayout.removeView(mDeleteBtn);
mDeleteBtn = null;
isDeleteShown = false;
mOnDeleteListener.onDelete(mSelectedItem);
}
});
mItemLayout = (ViewGroup) getChildAt(mSelectedItem
- getFirstVisiblePosition());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
params.addRule(RelativeLayout.CENTER_VERTICAL);
mItemLayout.addView(mDeleteBtn, params);
isDeleteShown = true;
}
return false;
}
// 隐藏删除按钮
public void hideDelete() {
mItemLayout.removeView(mDeleteBtn);
mDeleteBtn = null;
isDeleteShown = false;
}
public boolean isDeleteShown() {
return isDeleteShown;
}
/**
* 后面几个方法本例中没有用到
*/
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
}
3、定义列表项布局custom_listview_item.xml,它的结构很简单,只包含了一个TextView:
public class CustomListViewAdapter extends ArrayAdapter {
public CustomListViewAdapter(Context context, int textViewResourceId,
List objects) {
super(context, textViewResourceId, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(
R.layout.custom_listview_item, null);
} else {
view = convertView;
}
TextView contentTv = (TextView) view.findViewById(R.id.content_tv);
contentTv.setText(getItem(position));
return view;
}
}
public class MainActivity extends Activity {
// 自定义Lv
private CustomListView mCustomLv;
// 自定义适配器
private CustomListViewAdapter mAdapter;
// 内容列表
private List contentList = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initContentList();
mCustomLv = (CustomListView) findViewById(R.id.custom_lv);
mCustomLv.setOnDeleteListener(new OnDeleteListener() {
@Override
public void onDelete(int index) {
contentList.remove(index);
mAdapter.notifyDataSetChanged();
}
});
mAdapter = new CustomListViewAdapter(this, 0, contentList);
mCustomLv.setAdapter(mAdapter);
}
// 初始化内容列表
private void initContentList() {
for (int i = 0; i < 20; i++) {
contentList.add("内容项" + i);
}
}
@Override
public void onBackPressed() {
if (mCustomLv.isDeleteShown()) {
mCustomLv.hideDelete();
return;
}
super.onBackPressed();
}
}