【0058】自定义控件-2-完全自定义控件.(ViewGroup)-侧滑面板

1.侧滑面板效果

【说明】继承ViewGroup,因为其中包含有许多的小的条目,比如新闻、订阅等等;

2.布局

【说明】

(1)分为左面板和主面板

(2)使用帧布局;

(3)新知识点的使用:include的使用,在xml布局中包含另外一个布局(include)

2.1 左面板ScrollView 布局

2.1.1 背景图片的添加

 【取色器】

2.1.2 单个textView的设置和图片添加

【抽取样式源码】

 1 <resources>
 2 
 3     <!--
 4         Base application theme, dependent on API level. This theme is replaced
 5         by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
 6     -->
 7     <style name="AppBaseTheme" parent="android:Theme.Light">
 8         <!--
 9             Theme customizations available in newer API levels can go in
10             res/values-vXX/styles.xml, while customizations related to
11             backward-compatibility can go here.
12         -->
13     </style>
14 
15     <!-- Application theme. -->
16     <style name="AppTheme" parent="AppBaseTheme">
17         <!-- All customizations that are NOT specific to a particular API-level can go here. -->
18     </style>
19 
20     
21     <style name="style_bt_text" parent="android:Widget.Holo.Light.TextView">
22         <item name="android:background">@drawable/selector_menu_bt_bg</item>
23         <item name="android:clickable">true</item>
24         <item name="android:drawablePadding">10dp</item>
25         <item name="android:gravity">center_vertical</item>
26         <item name="android:padding">8dp</item>
27         <item name="android:textColor">#ADCFD6</item>
28         <item name="android:textSize">18sp</item>
29         <item name="android:layout_width">match_parent</item>
30         <item name="android:layout_height">wrap_content</item>
31         <item name="android:onClick">onTabClick</item>
32     </style>
33 </resources>

 

【左侧面板布局源码】

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="240dp"
 4     android:layout_height="match_parent" >
 5 
 6     <LinearLayout
 7         android:layout_width="240dp"
 8         android:layout_height="match_parent"
 9         android:background="@drawable/menu_bg"
10         android:orientation="vertical" >
11 
12         <TextView
13             style="@style/style_bt_text"
14             android:drawableLeft="@drawable/tab_news"
15             android:text="新闻" />
16         
17         <TextView
18             style="@style/style_bt_text"
19             android:drawableLeft="@drawable/tab_read"
20             android:text="订阅" />
21         
22         <TextView
23             style="@style/style_bt_text"
24             android:drawableLeft="@drawable/tab_local"
25             android:text="本地" />
26         
27         <TextView
28             style="@style/style_bt_text"
29             android:drawableLeft="@drawable/tab_ties"
30             android:text="跟帖" />
31         
32         <TextView
33             style="@style/style_bt_text"
34             android:drawableLeft="@drawable/tab_pics"
35             android:text="图片" />
36         
37         <TextView
38             style="@style/style_bt_text"
39             android:drawableLeft="@drawable/tab_ugc"
40             android:text="话题" />
41         
42         <TextView
43             style="@style/style_bt_text"
44             android:drawableLeft="@drawable/tab_vote"
45             android:text="投票" />
46         <TextView
47             style="@style/style_bt_text"
48             android:drawableLeft="@drawable/tab_focus"
49             android:text="聚合阅读" />
50         
51     </LinearLayout>
52 
53 </ScrollView>

 

2.1.3 TextView的点击背景更改

【说明】默认是透明的,按下之后变为了蓝色

【说明】使用selector

【颜色的指定】

【布局当中颜色背景的添加】

2.1.4 左面板的整体布局的添加

【效果】

 3. 去掉左侧面板的标题

4.添加别的图标

4.1 抽取样式

 4.2 左侧面板源码

【layout_left_menu.xml源码】

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="240dp"
 4     android:layout_height="match_parent" >
 5 
 6     <LinearLayout
 7         android:layout_width="240dp"
 8         android:layout_height="match_parent"
 9         android:background="@drawable/menu_bg"
10         android:orientation="vertical" >
11 
12         <TextView
13             style="@style/style_bt_text"
14             android:drawableLeft="@drawable/tab_news"
15             android:text="新闻" />
16         
17         <TextView
18             style="@style/style_bt_text"
19             android:drawableLeft="@drawable/tab_read"
20             android:text="订阅" />
21         
22         <TextView
23             style="@style/style_bt_text"
24             android:drawableLeft="@drawable/tab_local"
25             android:text="本地" />
26         
27         <TextView
28             style="@style/style_bt_text"
29             android:drawableLeft="@drawable/tab_ties"
30             android:text="跟帖" />
31         
32         <TextView
33             style="@style/style_bt_text"
34             android:drawableLeft="@drawable/tab_pics"
35             android:text="图片" />
36         
37         <TextView
38             style="@style/style_bt_text"
39             android:drawableLeft="@drawable/tab_ugc"
40             android:text="话题" />
41         
42         <TextView
43             style="@style/style_bt_text"
44             android:drawableLeft="@drawable/tab_vote"
45             android:text="投票" />
46         <TextView
47             style="@style/style_bt_text"
48             android:drawableLeft="@drawable/tab_focus"
49             android:text="聚合阅读" />
50         
51     </LinearLayout>
52 
53 </ScrollView>

【colors.xml源码】

1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3     
4     <color name="bt_bg_pressed">#33ADCFD6</color>
5     
6 </resources>

【styles.xml新增的源码】

 1  
 2     <style name="style_bt_text" parent="android:Widget.Holo.Light.TextView">
 3         <item name="android:background">@drawable/selector_menu_bt_bg</item>
 4         <item name="android:clickable">true</item>
 5         <item name="android:drawablePadding">10dp</item>
 6         <item name="android:gravity">center_vertical</item>
 7         <item name="android:padding">8dp</item>
 8         <item name="android:textColor">#ADCFD6</item>
 9         <item name="android:textSize">18sp</item>
10         <item name="android:layout_width">match_parent</item>
11         <item name="android:layout_height">wrap_content</item>
12         <item name="android:onClick">onTabClick</item>
13     </style>

5.主面板布局的实现

5.1 布局中的线的添加

5.2 主面板布局的效果

【layout_main_content.xml主面板的源码】

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:background="#FFF"
 6     android:orientation="vertical" >
 7 
 8     <LinearLayout
 9         android:layout_width="match_parent"
10         android:layout_height="wrap_content"
11         android:background="@drawable/top_bar_bg"
12         android:orientation="horizontal" >
13 
14         <ImageButton
15             android:id="@+id/ib_back"
16             android:layout_width="wrap_content"
17             android:layout_height="wrap_content"
18             android:background="@null"
19             android:src="@drawable/main_back" />
20 
21         <View
22             android:layout_width="1dp"
23             android:layout_height="match_parent"
24             android:background="@drawable/top_bar_divider" />
25 
26         <TextView
27             android:layout_width="match_parent"
28             android:layout_height="wrap_content"
29             android:layout_gravity="center_vertical"
30             android:layout_marginLeft="10dp"
31             android:text="黑马新闻"
32             android:textColor="#FFF"
33             android:textSize="24sp" />
34     </LinearLayout>
35 
36     <TextView
37         android:layout_width="match_parent"
38         android:layout_height="match_parent"
39         android:gravity="center"
40         android:text="钓鱼岛是中国的! 苍老师才是世界的."
41         android:textSize="26dp" />
42 
43 </LinearLayout>

【activity_main.xml源码】使用include关键字,可以包含别的布局;

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     tools:context=".MainActivity" >
 6 
 7     <com.itheima74.sliding.ui.SlideMenu
 8         android:id="@+id/sm"
 9         android:layout_width="match_parent"
10         android:layout_height="match_parent" >
11         
12         <include layout="@layout/layout_left_menu"/>
13         
14         <include layout="@layout/layout_main_content"/>"
15         
16     </com.itheima74.sliding.ui.SlideMenu>
17 
18 </RelativeLayout>

6. 布局的层级关系

【使用帧布局的层级关系】主面板将左侧面板进行了覆盖;

【解决方法】需要使用ViewGroup将左侧面板放到显示的屏幕的外边;

 

【注意】此处没有调用 onDraw()方法;

6.1 onMeasure方法

【onMeasure】测量孩子的宽高

【找到孩子】首先在测量孩子的位置的时候需要找到孩子,孩子本身就是一个集合了,如第一个左侧面就是0号位;第二个主面板就是1号位;

6.2 onLayout方法的书写

【说明】如果没有经过摆放的效果是空白的,就比如家里的布局测量好之后,家具没有摆放;

 

【控件摆放的坐标位置的确定】

【源码】

 1     /**
 2      * changed: 当前控件的尺寸大小, 位置 是否发生了变化
 3      * left:当前控件 左边距
 4      * top:当前控件 顶边距
 5      * right:当前控件 右边界
 6      * bottom:当前控件 下边界
 7      */
 8     @Override
 9     protected void onLayout(boolean changed, int l, int t, int r, int b) {
10         
11         // 摆放内容, 左面板
12         View leftMenu = getChildAt(0);
13         leftMenu.layout(-leftMenu.getMeasuredWidth(), 0, 0, b);
14         
15         // 主面板
16         getChildAt(1).layout(l, t, r, b);
17     }

7.触摸事件

7.1 触摸事件的返回值的确定

【说明】如果使用的已有控件的组合,则返回值是super,因为要使得原来的已有控件生效;

   如果完全自定义的控件,则返回值是true;

7.2 scrollTo&scrollBy滚动内容

7.2.1 srollTo 和srollBy原理

7.2.2 完成滑动事件

7.2.3 限定边界

【说明】在面板进行滑动的时候,左侧面板会超出左边界,主面板会超出右边界;需要进行限定;

8. 界面跳转的实现(方法1)

9. 平滑动画的实现scroller(方法2)

9.1 scroller对象的创建

【说明】在构造方法中创建,为了创建一份对象;

9.2 源码

 【源码】

 1     /**
 2      * 根据当前的状态, 执行 关闭/开启 的动画
 3      */
 4     private void updateCurrentContent() {
 5         int startX = getScrollX();
 6         int dx = 0;
 7         // 平滑滚动
 8         if(currentState == MENU_STATE){
 9             // 打开菜单
10 //            scrollTo(-getChildAt(0).getMeasuredWidth(), 0);
11 //            dx = 结束位置(-240) - 开始位置(-200) = -40
12 //            dx = 0 - (-10) = 10
13             
14             dx = -getChildAt(0).getMeasuredWidth() - startX;
15             
16         } else {
17             // 恢复主界面
18 //            scrollTo(0, 0);
19             
20             dx = 0 - startX;
21         }
22         
23         // startX: 开始的x值
24         // startY: 开始的y值
25         // dx: 将要发生的水平变化量. 移动的x距离
26         // dy: 将要发生的竖直变化量. 移动的y距离
27         // duration : 数据模拟持续的时长
28         
29         // 1. 开始平滑的数据模拟
30         int duration = Math.abs(dx * 2); // 0 -> 1200
31         scroller.startScroll(startX, 0, dx, 0, duration);
32         
33 //        - 200 -> -240
34 //        - 201 -> -202 -> -203 .... -236 -> -240
35         
36         invalidate();// 重绘界面 -> drawChild() -> computeScroll(),下面的方法会被调用; 
37     }
38     
39     //2. 维持动画的继续
40     @Override
41     public void computeScroll() {
42         super.computeScroll();
43         if(scroller.computeScrollOffset()){ // 直到duration事件以后, 结束
44             // true, 动画还没有结束
45             // 获取当前模拟的数据, 也就是要滚动到的位置
46             int currX = scroller.getCurrX(); 
47             System.out.println("currX: " + currX);
48             scrollTo(currX, 0); // 滚过去
49             
50             invalidate(); // 重绘界面-> drawChild() -> computeScroll();循环
51         }
52     }

10 添加开关功能

10.1 功能描述

 

10.2 源码

11. 触摸事件的截获

11.1 按钮按下的拦截机制的原理

【说明】在FrameLayout的布局中进行事件拦截的判断,避免事件在下面的按钮中事件不再返回;

 

 

11.2 源码

 1     
 2     
 3     /**
 4      * 拦截判断
 5      */
 6     @Override
 7     public boolean onInterceptTouchEvent(MotionEvent ev) {
 8         
 9         switch (ev.getAction()) {
10         case MotionEvent.ACTION_DOWN:
11             downX = ev.getX();
12             downY = ev.getY();
13             break;
14         case MotionEvent.ACTION_MOVE:
15             
16             float xOffset = Math.abs(ev.getX() - downX);
17             float yOffset = Math.abs(ev.getY() - downY);
18             
19             if(xOffset > yOffset && xOffset > 5){ // 水平方向超出一定距离时,才拦截;细节:5dp定义是因为在手指可能轻轻的左右滑动,也要响应滑动事件;
20                 return true; // 拦截此次触摸事件, 界面的滚动 拦截事件的核心
21             }
22             
23             break;
24         case MotionEvent.ACTION_UP:
25             
26             break;
27 
28         default:
29             break;
30         }
31         return super.onInterceptTouchEvent(ev);
32     }
33 
34 }

 

posted @ 2018-01-06 14:54  OzTaking  阅读(185)  评论(0)    收藏  举报