zoukankan      html  css  js  c++  java
  • Android自定义控件

    android自定义控件

    为什么我们需要自定义控件呢?

    • Android自身带的控件不能满足需求, 需要根据自己的需求定义控件.
    • 很多时候没有我们需要使用的控件,或者控件并不美观。
        Android本身提供了很多控件比如我们常用的有
          文本控件TextView和EditText;
          按钮控件Button和ImageButton
          状态开关按钮ToggleButton
          单选复选按钮RadioButton和RadioGroup
          单选按钮和复选按钮CheckBox
          图片控件ImageView
          时钟控件AnalogClock和DigitalClock
          进度条ProgressBar和日期与时间选择控件DatePicker和TimePicker等。
    

    Android本身提供的基本控件

    1 文本控件TextView 和EditText

    • TextView 控件继承自 View 类。TextView控件的功能是向用户显示文本内容同时可选择性让用户编辑文本。其中TextView不允许编辑。
    • EditText控件 EditText 控件继承自 TextView。EditText与TextView 最大的不同是 EditText是可以编辑的

    2 按钮控件Button 和 ImageButton

    • Button控件继承自 TextView 类Button 的用法比较简单主要是为 Button 控件设置 View.OnClickListener.监听器并在监听器的实现代码中编写按钮按下事件的处理代码。
    • ImageButton 控件 ImageButton 继承自 ImageView。ImageButton 与Button最大的区别是ImageButton没有text 属性既按钮中将显示图片而不是文本。 ImageButton 控件中设置显示图片可以通过android:src 属性也可以通过setImageResurce(int ) 方法来实现

    3 状态开关按钮ToggleButton

    • CheckBox 和RadioButton 都只有选中和未选中两种状态,可以通过checked属性来设置.
    • 不同的是RadioButton 是单选按钮,需要编制到一个RadioGroup中同一时刻一个RadioGroup中只能有一个按钮处于选中状态.
    • CheckBox和RadioButton 都是继承自 CompoundButton 中继承了一些成员.

    4 图片控件ImageView

    • ImageView 控件负责显示图片,其图片来源既可以是资源文件的id,也可以是Drawable对象或 Bitmap 对象,还可以是 Content Provider 的Uri.

    5 时钟控件AnalogClock 和 DigitalClock

    • AnalogClock继承自 ViewAnalogClock 控件显示模拟时钟只显示时针和分针
    • DigeitalClock 继承自 TextView。DigetalClock 显示数字时钟可精确到秒。 时钟控件比较简单只需要在布局文件中声明控件即可。

    6 日期与时间选择控件DatePicker 和 TimePicker

    • DatePicker 继承自FrameLayout类日期选择控件的主要功能是向用户提供包含年、月、日的日期数据并允许用户对其进行选择。如果要捕获用户修改日期选择控件中数据的事件需要为DatePicker 添加 onDateChangedListener 监听器。
    • TimePicker 同样继承自FrameLayout 类。时间选择控件向用户显示一天中的时间可以为24小时制可以为AM/PM 制�并允许用户进行选择。如果要捕获用户修改时间数据的事件便需要为TimePicker 添加OnTimeChangedListener 监听器

    怎么自定义空间呢?

    原理:继承已有控件实现自定义控件

    1. 通过对android本身提供的控件的代码进行研究,android中控件都是继承view类来实现,通过重写ondraw方法来绘制我们所需要的控件.通过这个我们得到两点提示:
    • 我们可以在已有的控件的基础上,通过重写相关方法来实现我们的需求.
    • 继承view类或viewgroup类,来绘制我们所需要的控件.一般来讲,通过继承已有的控件,来自定义控件要简单一点.
    1. 组合已有控件实现自定义控件
      组合已有控件实现自定义控件
    2. 完全自定义控件实现需求
      完全自定义控件实现需求
    3. 继承已有控件实现自定义控件
      继承已有控件实现自定义控件

    自定义控件可以分为三大类型

    1. 组合已有的控件实现

    1. 优酷菜单
    • 在xml布局里摆放好.
    • 给指定控件添加点击事件.
    • 根据业务逻辑,执行动画(旋转动画: 补间动画).
    • 菜单按钮的截获.
    1. 轮播图广告
    • 让图片滑动起来(ViewPager).
    • 让图片和文字,指示器对应起来.
    • 让轮播器无限循环
    1. 轮播器自动轮询
    向右无限循环  
    	0 -> 4	newPosition = position % 5  
    	5 -> 0  
    	6 -> 1  
    	7 -> 2  
    	8 -> 3  
    	9 -> 4  
    	10 -> 0  
    向左无限循环  
    设置到中间某个位置.
    
    1. 下拉选择框
    • Button或ImageButton等自带按钮功能的控件会抢夺所在Layout的焦点.导致其他区域点击不生效.在所在layout声明一个属性
    android:descendantFocusability="blocksDescendants"	
    
    • popupwindow获取焦点, 外部可点击
    // 设置点击外部区域, 自动隐藏
    popupWindow.setOutsideTouchable(true); // 外部可触摸
    popupWindow.setBackgroundDrawable(new BitmapDrawable()); // 设置空的背景, 响应点击事件		
    popupWindow.setFocusable(true); //设置可获取焦点
    
    ListView初始化
    PopupWindow初始化
    

    2. 完全自定义控件.(继承View, ViewGroup)

    • 自定义开关 (View)
    1. 写个类继承View, OK
    2. 拷贝包含包名的全路径到xml中, OK
    3. 界面中找到该控件, 设置初始信息, OK
    4. 根据需求绘制界面内容,OK
    5. 响应用户的触摸事件,OK
    6. 创建一个状态更新监听.OK
    7. 自定义属性.OK
    • 侧滑面板(ViewGroup)
    1. 在xml布局里摆放内容.
      侧滑面板页面布局
    <TextView
     style="@style/style_bt_text"
     android:drawableLeft="@drawable/tab_news"
     android:text="新闻" />
            
    <TextView
     style="@style/style_bt_text"
     android:drawableLeft="@drawable/tab_read"
     android:text="订阅" />
            
    <TextView
     style="@style/style_bt_text"
     android:drawableLeft="@drawable/tab_local"
     android:text="本地" />
            
    <TextView
     style="@style/style_bt_text"
     android:drawableLeft="@drawable/tab_ties"
     android:text="跟帖" />
            
    <TextView
     style="@style/style_bt_text"
     android:drawableLeft="@drawable/tab_pics"
     android:text="图片" />
            
    <TextView
     style="@style/style_bt_text"
     android:drawableLeft="@drawable/tab_ugc"
     android:text="话题" />
            
    <TextView
     style="@style/style_bt_text"
     android:drawableLeft="@drawable/tab_vote"
     android:text="投票" />
    <TextView
     style="@style/style_bt_text"
     android:drawableLeft="@drawable/tab_focus"
     android:text="聚合阅读" />        
    </LinearLayout>
    </ScrollView>
    
    1. 在自定义ViewGroup里, 进行measure测量, layout布局
    2. 响应用户的触摸事件
      触摸事件的传递机制
    3. int scrollX = (int) (downX - moveX);
    4. getScrollX()获取当前滚动到的位置
    5. 平滑动画
      侧滑面板
    //1. 开始模拟数据
    
     scroller.startScroll(startX, 0, dx, 0, duration);
     invalidate();// 重绘界面 -> drawChild() -> computeScroll();
    
    //2. 在computeScroll中不断获取模拟的数值
    
     @Override
     public void computeScroll() {
     super.computeScroll();
     if(scroller.computeScrollOffset()){
    // true, 动画还没有结束
    // 获取当前模拟的数据, 也就是要滚动到的位置
     int currX = scroller.getCurrX(); 
     scrollTo(currX, 0); // 滚过去
    				
     invalidate(); // 重绘界面
    }
    }
    

    3. 继承已有的控件实现(扩展已有的功能)

    • 包含下拉刷新功能的ListView
    1. 添加了自定义的头布局
      自定义的头布局
    <FrameLayout
            android:layout_margin="5dp"
            android:layout_width="50dp"
            android:layout_height="50dp" >
    
            <ImageView
                android:id="@+id/iv_arrow"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:src="@drawable/common_listview_headview_red_arrow" />
    
            <ProgressBar
                android:id="@+id/pb"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:indeterminateDrawable="@drawable/shape_progress"
                android:visibility="invisible" />
        </FrameLayout>
    
    1. 默认让头布局隐藏setPadding.设置 -自身的高度
    2. ListView下拉的时候, 修改paddingTop, 让头布局显示出来
    3. 触摸动态修改头布局, 根据paddingTop.
      - paddingTop = 0 完全显示
      - paddingTop < 不完全显示 -64(自身高度)完全隐藏
      - paddingTop > 0 顶部空白
    1. 松手之后根据当前的paddingTop决定是否执行刷新
      - paddingTop < 0 不完全显示, 恢复
      - paddingTop >= 0 完全显示, 执行正在刷新...
    /**
     * 根据状态更新头布局内容
     */
    private void updateHeader() {
    	switch (currentState) {
    	case PULL_TO_REFRESH: // 切换回下拉刷新
    	// 做动画, 改标题
    	mArrowView.startAnimation(rotateDownAnim);
    	mTitleText.setText("下拉刷新");
    		break;
    	case RELEASE_REFRESH: // 切换成释放刷新
    	// 做动画, 改标题
    	mArrowView.startAnimation(rotateUpAnim);
    	mTitleText.setText("释放刷新");		
    		break;
    	case REFRESHING: // 刷新中...
    	mArrowView.clearAnimation();
    	mArrowView.setVisibility(View.INVISIBLE);
    	pb.setVisibility(View.VISIBLE);
    	mTitleText.setText("正在刷新中...");
    			
    if(mListener != null){
        mListener.onRefresh(); // 通知调用者, 让其到网络加载更多数据.
    }			
    		break;
    		default:
    		break;
    }
    }
    
  • 相关阅读:
    CentOS虚拟机和物理机共享文件夹实现
    集训第六周 数学概念与方法 概率 数论 最大公约数 G题
    集训第六周 数学概念与方法 概率 F题
    集训第六周 E题
    集训第六周 古典概型 期望 D题 Discovering Gold 期望
    集训第六周 古典概型 期望 C题
    集训第六周 数学概念与方法 UVA 11181 条件概率
    集训第六周 数学概念与方法 UVA 11722 几何概型
    DAG模型(矩形嵌套)
    集训第五周 动态规划 K题 背包
  • 原文地址:https://www.cnblogs.com/stephenhuashao/p/5607536.html
Copyright © 2011-2022 走看看