参考文章: http://blog.csdn.net/guolin_blog/article/details/12921889
Android LayoutInflater原理分析,带你一步步深入了解View(一)
Android自定义View的实现方法,带你一步步深入了解View(四)
这里面总共有三种自定义控件:
自绘控件、组合控件、继承控件
?
- 自绘控件
- package com.example.DefineView1;
- ?
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Rect;
- import android.util.AttributeSet;
- import android.view.View;
- ?
- /**
- ?* Created by zhuxuekui on 2015/5/18.
- ?*/
- ?
- /**
- ?* 自定义组合控件之 自绘控件
- ?*/
- public
class CounterView extends View implements View.OnClickListener { - ?
- ????private Paint mPaint;
- ????private Rect mBounds;
- ????private
int mCount; - ????public CounterView(Context context, AttributeSet attrs) {
- ????????super(context, attrs);
- ????????mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- ????????mBounds = new Rect();
- ????????setOnClickListener(this);
- ?
- ????}
- ?
- [email protected]
- ????protected
void onDraw(Canvas canvas) { - ????????super.onDraw(canvas);
- ????????mPaint.setColor(Color.BLUE);
- ????????canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
- ????????mPaint.setColor(Color.YELLOW);
- ????????mPaint.setTextSize(30);
- ????????String text = String.valueOf(mCount);
- ????????mPaint.getTextBounds(text,0,text.length(),mBounds);// 获取文字区域(其实是一个mBounds)的宽度与高度,然后回调。
- ????????float textWidth = mBounds.width();
- ????????float textHeight = mBounds.height();
- ????????canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2
- ????????????????+ textHeight / 2, mPaint); //在画布上绘制文字
- ????}
- ?
- [email protected]
- ????public
void onClick(View view) { - ??????????mCount++;
- ??????????invalidate(); //重绘
- ????}
- }
在CounterView中,我们先初始化一些数据,然后设置view的点击事件。然后调用onclick方法,这里面有invalidate方法,重绘命令。然后调用ondraw方法,开始进行视图的绘制。
?
- package com.example.DefineView1;
- ?
- import android.app.Activity;
- import android.os.Bundle;
- ?
- public
class MyActivity extends Activity { - ????/**
- ?????* Called when the activity is first created.
- ?????*/
- [email protected]
- ????public
void onCreate(Bundle savedInstanceState) { - ????????super.onCreate(savedInstanceState);
- ????????setContentView(R.layout.main);
- ????}
- }
?
?
- 组合控件
程序结构:
- package com.example.DefineView2;
- ?
- import android.app.Activity;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.widget.Button;
- import android.widget.FrameLayout;
- import android.widget.TextView;
- ?
- /**
- ?* Created by zhuxuekui on 2015/5/18.
- ?*/
- public
class TitleView extends FrameLayout { - ?
- ????private Button leftButton;
- ????private TextView titleText;
- ????public TitleView(Context context, 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);
- ????????leftButton.setOnClickListener(new OnClickListener() {
- [email protected]
- ????????????public
void onClick(View view) { - ????????????????((Activity)getContext()).finish();
- ????????????}
- ????????});
- ????}
- ?
- ????public
void setTitleText(String text) - ????{
- ????????titleText.setText(text);
- ????}
- ?
- ????public
void setLeftButtonText(String text) - ????{
- ????????leftButton.setText(text);
- ????}
- ?
- ????public
void setLeftButtonListener(OnClickListener l) - ????{
- ????????leftButton.setOnClickListener(l);
- ????}
- }
首先我们定义title.xml下面的,然后定义TextView 继承FragmentLayout ,代码如上面的所示。里面我们对xml里面的控件进行初始化,设置事件都可以。
?
?
?
?
- 继承控件
截图:
程序结构:
?
?
1)增加的小按钮,只有一个button,没有布局
Delete_button.xml 子定义的listview里面增加的内容
?
2)编写我们自己的mylistview类
Mylistview
- package com.example.DefineView3;
- ?
- import android.content.Context;
- import android.util.AttributeSet;
- import android.view.*;
- import android.widget.ListView;
- import android.widget.RelativeLayout;
- ?
- /**
- ?* Created by zhuxuekui on 2015/5/18.
- ?*/
- public
class MyListView extends ListView implements View.OnTouchListener,GestureDetector.OnGestureListener { - ????private GestureDetector gestureDetector;
- ????private OnDeleteListener listener;
- ????private View deleteButton;
- ????private ViewGroup itemLayout;
- ????private
int selectedItem; - ????private
boolean isDeleteShown; - ?
- ????public MyListView(Context context, AttributeSet attrs) {
- ????????super(context, attrs);
- ????????gestureDetector = new GestureDetector(getContext(),this);
- ????????setOnTouchListener(this);
- ????}
- ?
- ????public
void setOnDeleteListener(OnDeleteListener l) - ????{
- ????????listener = l;
- ????}
- ?
- ?
- ?
- ?
- [email protected]
- ????public
boolean onTouch(View view, MotionEvent motionEvent) { - ????????if(isDeleteShown){
- ????????????itemLayout.removeView(deleteButton);
- ????????????deleteButton = null;
- ????????????isDeleteShown = false;
- ????????????return
false; - ????????}else{
- ????????????return gestureDetector.onTouchEvent(motionEvent);
- ????????}
- ????}
- ?
- //下面几个方法是OnTouchEvent的事件处理
- ?
- ????/**
- ?????* 手指按下事件处理
- ?????* @param motionEvent
- ?????* @return
- ?????*/
- [email protected]
- ????public
boolean onDown(MotionEvent motionEvent) { - ????????if(!isDeleteShown)
- ????????{
- ????????????selectedItem = pointToPosition((int)motionEvent.getX(),(int)motionEvent.getY());//判断当前选中的是listview的第几行
- ????????}
- ????????return
false; - ????}
- ?
- ????/**
- ?????* 快速滑动事件处理
- ?????* @param motionEvent
- ?????* @param motionEvent1
- ?????* @param X
- ?????* @param Y
- ?????* @return
- ?????*/
- [email protected]
- ????public
boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float X, float Y) { - ?
- ????????// 快速滑动到某一行上,加载布局deleteButton,并将删除按钮添加到当前选中的那一行item中
- ????????if(!isDeleteShown && Math.abs(X) > Math.abs(Y)){
- ????????????deleteButton = LayoutInflater.from(getContext()).inflate(R.layout.delete_button,null);
- ????????????deleteButton.setOnClickListener(new OnClickListener() {
- [email protected]
- ????????????????public
void onClick(View view) { - ????????????????????//当点击了删除按钮,我们就去回调onDeleteListener的onDelete()方法
- ????????????????????itemLayout.removeView(deleteButton);
- ????????????????????deleteButton = null;
- ????????????????????isDeleteShown = false;
- ????????????????????listener.onDelete(selectedItem);
- ????????????????}
- ????????????});
- ?
- ????????????itemLayout = (ViewGroup)getChildAt(selectedItem - getFirstVisiblePosition());
- ????????????RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
- ????????????params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
- ????????????params.addRule(RelativeLayout.CENTER_VERTICAL);
- ????????????itemLayout.addView(deleteButton, params);
- ????????????isDeleteShown = true;
- ????????}
- ?
- ????????return
false; - ????}
- ?
- [email protected]
- ????public
void onShowPress(MotionEvent motionEvent) { - ?
- ????}
- ?
- [email protected]
- ????public
boolean onSingleTapUp(MotionEvent motionEvent) { - ????????return
false; - ????}
- ?
- [email protected]
- ????public
boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) { - ????????return
false; - ????}
- ?
- [email protected]
- ????public
void onLongPress(MotionEvent motionEvent) { - ?
- ????}
- ?
- ????public
interface OnDeleteListener{ - ????????void onDelete(int index);
- ????}
- }
先去执行构造方法,创建gestureDetector手势捕捉监听程序,以及注册了ontouch监听。当我们按下的时候,触屏就算,程序执行到onTouch() 中,如果删除按钮已经显示我们删除掉图标,如果没有显示删除图标,我们使用gestureDetector来处理当前手势。然后我们执行gestureDetector.onTouchEvent(motionEvent) 。这里面包含多个方法,首先是onDown(),捕捉我们的手指按在了哪一行,我们记录下,滑动的时候,执行onfling(),
当按钮没有显示,然后我们去加载delete_button.xml此布局,然后并将其现在在listview当前选择的那一行上面,当我们点击删除图标的时候,执行回调方法,执行相应的逻辑。这部分逻辑在主界面中完成。
?
?
3)建立listview里面的子项
至此,新建上面的mylistview里面的每一个子项,my_list_view_item.xml.
My_list_view_item.xml listview 的子项
?
?
4)建立适配器类,继承ArrayAdapter
?
下一步就是新建适配器类
- package com.example.DefineView3;
- ?
- import android.content.Context;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.ArrayAdapter;
- import android.widget.TextView;
- ?
- import java.util.List;
- ?
- /**
- ?* Created by zhuxuekui on 2015/5/18.
- ?*/
- public
class MyAdapter extends ArrayAdapter<String> { - ?
- ????public MyAdapter(Context context, int resource, List<String> objects) {
- ????????super(context, resource, objects);
- ????}
- ?
- [email protected]
- ????public View getView(int position, View convertView, ViewGroup parent) {
- ????????View view;
- ????????if(convertView == null)
- ????????{
- ????????????view = LayoutInflater.from(getContext()).inflate(R.layout.my_list_view_item,null);
- ????????}else{
- ????????????view = convertView;
- ????????}
- ?
- ????????TextView textView = (TextView)view.findViewById(R.id.text_view);
- ????????textView.setText(getItem(position));
- ????????return view;
- ????}
- }
这一步主要就是重载ArrayAdapter,并重写构造方法和getview方法。
?
5)编写主界面的布局,使用自定义的listview控件
?
Mail.xml 布局自定义的listview
?
?
6)写主界面myactivity.java
- package com.example.DefineView3;
- ?
- import android.app.Activity;
- import android.os.Bundle;
- ?
- import java.util.ArrayList;
- import java.util.List;
- ?
- ?
- /**
- ?* 自定义控件3 之 继承控件
- ?*/
- public
class MyActivity extends Activity { - ?
- ????private MyListView myListView;
- ????private MyAdapter adapter;
- ????private List<String> contentList = new ArrayList<String>();
- ?
- ????/**
- ?????* Called when the activity is first created.
- ?????*/
- [email protected]
- ????public
void onCreate(Bundle savedInstanceState) { - ????????super.onCreate(savedInstanceState);
- ????????setContentView(R.layout.main);
- ????????initList();
- ????????myListView = (MyListView)findViewById(R.id.my_list_view);
- ????????myListView.setOnDeleteListener(new MyListView.OnDeleteListener() {
- [email protected]
- ????????????public
void onDelete(int index) { - ????????????????contentList.remove(index);
- ????????????????adapter.notifyDataSetChanged();
- ????????????}
- ????????});
- ?
- ????????adapter = new MyAdapter(this,0,contentList);
- ????????myListView.setAdapter(adapter);
- ????}
- ?
- ????private
void initList(){ - ????????contentList.add("Content Item 1");
- ????????contentList.add("Content Item 2");
- ????????contentList.add("Content Item 3");
- ????????contentList.add("Content Item 4");
- ????????contentList.add("Content Item 5");
- ????????contentList.add("Content Item 6");
- ????????contentList.add("Content Item 7");
- ????????contentList.add("Content Item 8");
- ????????contentList.add("Content Item 9");
- ????????contentList.add("Content Item 10");
- ????????contentList.add("Content Item 11");
- ????????contentList.add("Content Item 12");
- ????????contentList.add("Content Item 13");
- ????????contentList.add("Content Item 14");
- ????????contentList.add("Content Item 15");
- ????????contentList.add("Content Item 16");
- ????????contentList.add("Content Item 17");
- ????????contentList.add("Content Item 18");
- ????????contentList.add("Content Item 19");
- ????????contentList.add("Content Item 20");
- ????}
- }