zoukankan      html  css  js  c++  java
  • 安卓学习-界面-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
  • 相关阅读:
    oracle 导入数据时提示只有 DBA 才能导入由其他 DBA 导出的文件
    oracle 常用语句
    android udp 无法收到数据 (模拟器中)
    android DatagramSocket send 发送数据出错
    AtCoder ABC 128E Roadwork
    AtCoder ABC 128D equeue
    AtCoder ABC 127F Absolute Minima
    AtCoder ABC 127E Cell Distance
    CodeForces 1166E The LCMs Must be Large
    CodeForces 1166D Cute Sequences
  • 原文地址:https://www.cnblogs.com/weijj/p/3921983.html
Copyright © 2011-2022 走看看