Android ApiDemos示例解析(118):Views->Focus->4. Internal Selection
2012-08-11 17:21
543 查看
使用方向键或是traceball 移动UI焦点时,有一些UI控件,如Listview ,GridView 内部可以带有子UI (如列表项,Cell项),当Focus移动到这类UI控件后,再使用使用方向键或是traceball 可以在Listview 或是 GridView 内部移动当前选中的列表项或是Cell项等。
本例介绍了一个自定义UI控件InternalSelectionView ,自定义UI控件的步骤可以参见Android ApiDemos示例解析(109):Views->Custom
InternalSelectionView 可以显示一个矩形列表,矩形的宽度为View的宽度,允许自定义列表的行数,矩形的高度为View的高度平分为列表的行数。缺省行数为5.
其onDraw 显示 矩形,并以高亮(红色)显示当前选中的矩形。否则以黑色显示.
注:黑色背景矩形显示看不大清楚,这里改为绿色。
和UI焦点(Focus)相关的几个方法如下:
1. 处理方向键“上”,“下” ,InternalSelectionView 显示了一个纵向矩形列表,可以使用“上”,“下”键移动InternalSelectionView 当前选中的矩形。
2. 重载getFocusedRect 方法,设置被选中区域矩形框大小, 缺省情况(对应没有内部选择功能的UI控件) getFocusedRect 和 getDrawingRect大小相同,也就是和View大小相同。当将UI焦点从本控件移动到下一个UI控件时,Android系统将根据本UI控件的Focused Rect位置根据UI焦点移动的方向找到和这个Focused Rect距离最近的下一个UI控件。 对应支持内部选择的View(如本例或ListView)getFocusedRect 应正确设置选中区域矩形的大小:
本例将Focused Rect 设置成当前选中的矩形的大小。
3. 重载 onFocusChanged ,这个方法在当前UI View Focus状态发生变化时调用,状态为取得焦点和失去焦点。 重载时记住要调用基类的方法以保证标准Focus移动行为。
函数参数:
focused: 为true时表示此View获取焦点,否则为失去焦点。
direction: 当前焦点移动的方向,可以为上,下,左,右,前向或是后向。
previouslyFocusedRect: 不为null时表示前一个获取焦点UI控件(View整体)的矩形区域大小。
对于本例来说,只有FOCUS_LEFT 和 FOCUS_RIGHT 会被执行到。 InternalSelectionFocus 从左到右并排显示3个InternalSelectionView的示例。 “左”,“右”键可以在左,中,右三个InternalSelectionView 来回移动UI焦点。 “上”,“下”就可以在当前获取UI焦点的一个InternalSelectionView对象上下选择一个矩形。
看看“左”,“右”键移动UI焦点时,下一个获取焦点的InternalSelectionView 中哪个矩形会被选中:
由于三个View的顶部和底部对齐 ,也就是previouslyFocusedRect 的top 和bottom 对于当前选中哪个View都是一样的,因此算出来的mSelectuedRow 都一样,对应本例都为3. 因此使用”左”,”右” 移动UI焦点时,下一个获取焦点的InternalSelectionView 总是首先选中序号为3的矩形。
![](http://www.imobilebbs.com/wordpress/wp-content/uploads/2011/06/20110625001.png)
本例介绍了一个自定义UI控件InternalSelectionView ,自定义UI控件的步骤可以参见Android ApiDemos示例解析(109):Views->Custom
InternalSelectionView 可以显示一个矩形列表,矩形的宽度为View的宽度,允许自定义列表的行数,矩形的高度为View的高度平分为列表的行数。缺省行数为5.
其onDraw 显示 矩形,并以高亮(红色)显示当前选中的矩形。否则以黑色显示.
@Override protected void onDraw(Canvas canvas) { ... // draw forground rect if (i == mSelectedRow && hasFocus()) { mPainter.setColor(Color.RED); mPainter.setAlpha(0xF0); mTextPaint.setAlpha(0xFF); } else { mPainter.setColor(Color.GREEN); mPainter.setAlpha(0x40); mTextPaint.setAlpha(0xF0); } ... }
注:黑色背景矩形显示看不大清楚,这里改为绿色。
和UI焦点(Focus)相关的几个方法如下:
1. 处理方向键“上”,“下” ,InternalSelectionView 显示了一个纵向矩形列表,可以使用“上”,“下”键移动InternalSelectionView 当前选中的矩形。
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch(event.getKeyCode()) { case KeyEvent.KEYCODE_DPAD_UP: if (mSelectedRow > 0) { mSelectedRow--; invalidate(); ensureRectVisible(); return true; } break; case KeyEvent.KEYCODE_DPAD_DOWN: if (mSelectedRow < (mNumRows - 1)) { mSelectedRow++; invalidate(); ensureRectVisible(); return true; } break; } return false; }
2. 重载getFocusedRect 方法,设置被选中区域矩形框大小, 缺省情况(对应没有内部选择功能的UI控件) getFocusedRect 和 getDrawingRect大小相同,也就是和View大小相同。当将UI焦点从本控件移动到下一个UI控件时,Android系统将根据本UI控件的Focused Rect位置根据UI焦点移动的方向找到和这个Focused Rect距离最近的下一个UI控件。 对应支持内部选择的View(如本例或ListView)getFocusedRect 应正确设置选中区域矩形的大小:
@Override public void getFocusedRect(Rect r) { getRectForRow(r, mSelectedRow); } public void getRectForRow(Rect rect, int row) { final int rowHeight = getRowHeight(); final int top = getPaddingTop() + row * rowHeight; rect.set(getPaddingLeft(), top, getWidth() - getPaddingRight(), top + rowHeight); }
本例将Focused Rect 设置成当前选中的矩形的大小。
3. 重载 onFocusChanged ,这个方法在当前UI View Focus状态发生变化时调用,状态为取得焦点和失去焦点。 重载时记住要调用基类的方法以保证标准Focus移动行为。
@Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { super.onFocusChanged(focused, direction, previouslyFocusedRect); if (focused) { switch (direction) { case View.FOCUS_DOWN: mSelectedRow = 0; break; case View.FOCUS_UP: mSelectedRow = mNumRows - 1; break; case View.FOCUS_LEFT: // fall through case View.FOCUS_RIGHT: // set the row that is closest to the rect if (previouslyFocusedRect != null) { int y = previouslyFocusedRect.top + (previouslyFocusedRect.height() / 2); int yPerRow = getHeight() / mNumRows; mSelectedRow = y / yPerRow; } else { mSelectedRow = 0; } break; default: // can't gleam any useful information about what internal // selection should be... return; } invalidate(); } }
函数参数:
focused: 为true时表示此View获取焦点,否则为失去焦点。
direction: 当前焦点移动的方向,可以为上,下,左,右,前向或是后向。
previouslyFocusedRect: 不为null时表示前一个获取焦点UI控件(View整体)的矩形区域大小。
对于本例来说,只有FOCUS_LEFT 和 FOCUS_RIGHT 会被执行到。 InternalSelectionFocus 从左到右并排显示3个InternalSelectionView的示例。 “左”,“右”键可以在左,中,右三个InternalSelectionView 来回移动UI焦点。 “上”,“下”就可以在当前获取UI焦点的一个InternalSelectionView对象上下选择一个矩形。
看看“左”,“右”键移动UI焦点时,下一个获取焦点的InternalSelectionView 中哪个矩形会被选中:
if (previouslyFocusedRect != null) { int y = previouslyFocusedRect.top + (previouslyFocusedRect.height() / 2); int yPerRow = getHeight() / mNumRows; mSelectedRow = y / yPerRow; }
由于三个View的顶部和底部对齐 ,也就是previouslyFocusedRect 的top 和bottom 对于当前选中哪个View都是一样的,因此算出来的mSelectuedRow 都一样,对应本例都为3. 因此使用”左”,”右” 移动UI焦点时,下一个获取焦点的InternalSelectionView 总是首先选中序号为3的矩形。
![](http://www.imobilebbs.com/wordpress/wp-content/uploads/2011/06/20110625001.png)
相关文章推荐
- Android ApiDemos示例解析(115):Views->Focus->1. Vertical
- Android ApiDemos示例解析(116):Views->Focus->2. Horizontal
- Android ApiDemos示例解析(117):Views->Focus->3. Circular
- Android ApiDemos示例解析(106):Views->Chronometer
- Android ApiDemos示例解析(196):Views->TextSwitcher
- Android ApiDemos示例解析(156):Views->Layouts->TableLayout->01. Basic
- Android ApiDemos示例解析(134):Views->Layouts->Baseline->2. Bottom
- Android ApiDemos示例解析(162):Views->Layouts->TableLayout->07. Column Collapse
- Android ApiDemos示例解析(140):Views->Layouts->Baseline->Nested Example 3
- Android ApiDemos示例解析(142):Views->Layouts->LinearLayout->2. Vertical (Fill Screen)
- Android ApiDemos示例解析(164):Views->Layouts->TableLayout->09. Toggle Shrink
- Android ApiDemos示例解析(158):Views->Layouts->TableLayout->03.Long Content
- Android ApiDemos示例解析(135):Views->Layouts->Baseline->3. Center
- Android ApiDemos示例解析(176):Views->Lists->9. Array (Overlay)
- Android ApiDemos示例解析(177):Views->Lists->10. Single choice list
- Android ApiDemos示例解析(184):Views->Progress Bar->3. Dialogs
- Android ApiDemos示例解析(165):Views->Layouts->TableLayout->10. Simple Form
- Android ApiDemos示例解析(149):Views->Layouts->LinearLayout->9. Layout Weight
- Android ApiDemos示例解析(150):Views->Layouts->LinearLayout->10. Background Image
- Android ApiDemos示例解析(159):Views->Layouts->TableLayout->04.Stretchable