安卓学习-界面-View的自定义

android的所有UI控件,都是基于View的,因此特意重点学习了下这个,为后面学习其他控件打下基础。

参照了疯狂android讲义和http://blog.csdn.net/guolin_blog/article/details/17357967,还有几个例子到后面再写,主要是现在看不懂

重新时常用覆盖的方法

package com.example.ddddddd;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;

public class MyButton extends Button{

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    //窗口加载这个组件时会执行
    protected void onFinishInflate() {
        super.onFinishInflate();
        Log.d("test", "我被XML加载了");
    }
    
    //看不懂,不知道什么意思,解释如下
    //用来检测View组件和他包含的所有子组件的大小
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    
    //当该组件需要分配其子组件位置、大小时会调用该方法
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }
    
    //该组件大小被改变时会调用该方法
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        Log.d("test", "被改变大小了,原来w="+oldw+"y="+oldh+" 现在w="+w+"y="+h);
        super.onSizeChanged(w, h, oldw, oldh);
    }
    
    //要绘制该组件内容时回调该方法
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
    
    //光标在这个组件上,并且按键被按下时调用该方法
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.d("test", "按键"+keyCode+"按下了");
        return super.onKeyDown(keyCode, event);
    }
    
    //光标在这个组件上,并且按键松开时调用该方法
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        Log.d("test", "按键"+keyCode+"松开了");
        return super.onKeyUp(keyCode, event);
    }

    //发生轨迹球事件,不知道是个什么东西
    public boolean onTrackballEvent(MotionEvent event) {
        return super.onTrackballEvent(event);
    }
    
    //发生触摸屏事件,触发此方法
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("test", "我被触摸了,位置 X:"+event.getX()+" Y:"+event.getY());
        return super.onTouchEvent(event);
    }
    
    //当得到或失去焦点,触发
    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
        if(gainFocus){
            Log.d("test", "得到焦点");
        }else{
            Log.d("test", "失去焦点");
        }
        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
    }
    
    //该组件放入某个窗口时,触发
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
    }
    
    //组件从窗口上分离,触发
    protected void onDetachedFromWindow() {
        Log.d("test", "分离");
        super.onDetachedFromWindow();
    }
    
    //可见性发生改变时触发,一般调用setVisibility(View.GONE)
    protected void onVisibilityChanged(View changedView, int visibility) {
        Log.d("test", "摧毁");
        super.onVisibilityChanged(changedView, visibility);
    }

}
View Code

一个跟随手指移动的球

 

 

public class MyView extends View{

    public MyView(Context context) {
        super(context);
    }
    
    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    //定义一个画笔
    private Paint paint=new Paint();
    private float cx=0;
    private float cy=0;
    
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //设置画笔颜色,这里制定红色
        paint.setColor(Color.RED);
        //绘制一个位置在cx,cy的半径15,的圆
        canvas.drawCircle(cx, cy, 15, paint);
    }

    public boolean onTouchEvent(MotionEvent event) {
        cx=event.getX();
        cy=event.getY();
        //重绘
        invalidate();
        return true;
    }
}
View Code

 标题,参照网上的一个帖子做的

title.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="#ffcb05" >

    <Button
        android:id="@+id/button_left"
        android:layout_width="60dp"
        android:layout_height="40dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dp"
        android:background="@drawable/back_button"
        android:textColor="#fff" />

    <TextView
        android:id="@+id/title_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="标题"
        android:textColor="#fff"
        android:textSize="20sp" />

</RelativeLayout>
View Code

组件TitleView.java

public class TitleView extends FrameLayout {

    //左边返回的按钮
    private Button leftButton;
    //中间的标题文字
    private TextView titleText;

    //初始化
    public TitleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //获取XML配置文件
        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() {
            public void onClick(View v) {
                ((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);
    }
}
View Code

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.ddddddd.TitleView
        android:id="@+id/title_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </com.example.ddddddd.TitleView>

</RelativeLayout>
View Code

 

 

自动以ListView

当快速向右滑动时会显示一个Del按钮,点击可删除该条信息

1.按钮的自定义XML页面

del_button.xml

<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/button1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Del" />
View Code

2.ListView要用到的item

my_list_view_item.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="Large Text"        
        android:gravity="center_vertical"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>
View Code

3.自定义ListView

MyListView.java

这里面用到了OnTouchListener和OnGestureListener

通过onTouch触发OnGestureListener手势识别,当onFling执行时判断是否是横向快速滑动,是的话创建del_button.xml视图,并添加按钮事件

public class MyListView extends ListView implements OnTouchListener,OnGestureListener{

    private View delButton;
    private ViewGroup view;
    private int selectedItem;
    
    //删除事件
    private OnDeleteListener onDeleteListener;  
    
    //手势
    private GestureDetector gestureDetector; 
    
    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        gestureDetector = new GestureDetector(getContext(), this); 
        
        //这句也不要忘记
        setOnTouchListener(this); 
    }


    public void setOnDeleteListener(OnDeleteListener onDeleteListener) {
        this.onDeleteListener = onDeleteListener;
    }



    //必须写这个方法,然后将触摸的事件交给手势来做
    public boolean onTouch(View v, MotionEvent event) {
            //交给手势来处理
            return gestureDetector.onTouchEvent(event);

    }

    /*****************OnGestureListener接口的实现类******************/
    //每次按下都会触发
    public boolean onDown(MotionEvent e) {
        Log.v("wjj", "onDown");
        
        //按下就先清除原来的删除按钮
        if(delButton != null){
            view.removeView(delButton);
            delButton=null;
        }
    
        //pointToPosition 根据x,y获取item的位置
        selectedItem = pointToPosition((int) e.getX(), (int) e.getY()); 
        Log.v("wjj", "selectedItem="+selectedItem);
        
        return false;
    }

    //类似单击,按下后过一会才弹起,但还没达到longpress的标准
    //介于onSingleTapUp和onLongPress之间吧
    public void onShowPress(MotionEvent e) {
        Log.v("wjj", "onShowPress");
        
    }

    //类似单击,按下后马上弹起
    public boolean onSingleTapUp(MotionEvent e) {
        Log.v("wjj", "onSingleTapUp");
        return false;
    }

    //手指比较慢的滑动,可以纵向横向
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        //Log.v("wjj", "onScroll");
        return false;
    }

    //长按记录
    public void onLongPress(MotionEvent e) {
        Log.v("wjj", "onLongPress");    
        //长按时显示删除按钮
    }

    //手指快速的滑动,可以纵向横向
    //4个参数相当于向量 
    //e1为向量的起点,e2为向量的终点,velocityX为向量水平方向的速度,velocityY为向量垂直方向的速度
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        Log.v("wjj", "onFling");
        
        //水平方向速度大于垂直方向速度,认为是横向滑动
        if(Math.abs(velocityX)>Math.abs(velocityY)){
            //获取删除按钮视图
            delButton=LayoutInflater.from(getContext()).inflate(R.layout.del_button,null);
            delButton.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    Log.v("删除", selectedItem+"");
                    view.removeView(delButton);
                    delButton=null;
                    onDeleteListener.onDelete(selectedItem);
                }
            });

            //设置位置
            RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);  
            params.addRule(RelativeLayout.CENTER_VERTICAL); 
            
            //获得滑动位置的item
            //selectedItem onDown时获取,
            //当前显示的第一个getFirstVisiblePosition
            //getChildAt,比如当前总共显示10个,那么不管在那个位置,都是从0到9
            view=(ViewGroup)getChildAt(selectedItem-getFirstVisiblePosition());
            TextView tv=(TextView)view.findViewById(R.id.textView1);
            Log.v("wjj", "TextView "+tv.getText());
            view.addView(delButton,params);
        }
        return false;
    }

     //增加删除事件,方便外部调用
     public interface OnDeleteListener {  
            void onDelete(int index);  
     }  

}
View Code

4.自定义Adapter

MyAdapter.java

public class MyAdapter extends ArrayAdapter<String> {

    public MyAdapter(Context context, int resource, List<String> objects) {
        super(context, resource, objects);
        // TODO 自动生成的构造函数存根
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        //是否该视图已经存在
        if(convertView==null){
            //不存在,直接从xml加载视图
            view=LayoutInflater.from(getContext()).inflate(R.layout.my_list_view_item, null);
        }else{
            view=convertView;
        }
        //获取text
        TextView tv=(TextView)view.findViewById(R.id.textView1);
        //设置text的值
        tv.setText(getItem(position));
        //返回自定义view
        return view;
    }

}
View Code

5.主界面

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.ddddddd.MyListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true" >

    </com.example.ddddddd.MyListView>

</RelativeLayout>
View Code

MainActivity.java

public class MainActivity extends Activity {
    MyListView lv;
    private List<String> contentList = new ArrayList<String>();  
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        initList();
        
        lv=(MyListView)findViewById(R.id.listView1);
        lv.setAdapter(new MyAdapter(this, 0, contentList));
        lv.setOnDeleteListener(new OnDeleteListener() {
            public void onDelete(int index) {
                //删除
                contentList.remove(index);
                ((MyAdapter)lv.getAdapter()).notifyDataSetChanged();
            }
        });
        
    }

     private void initList() {  
             for(int i=1;i<=100;i++){
                 contentList.add("Content Item "+i);  
             }
    }  

}
View Code

 

posted on 2014-08-19 14:11  weijj  阅读(352)  评论(0编辑  收藏  举报

导航