当前位置:操作系统 > 安卓/Android >>

Android ApiDemos示例解析(118):Views->Focus->4. Internal Selection

上一篇:http://www.zzzyk.com/kf/201208/146799.html


使用方向键或是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 显示 矩形,并以高亮(红色)显示当前选中的矩形。否则以黑色显示.

[java]
@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); 

... 

@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 当前选中的矩形。

[java
@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; 

@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 应正确设置选中区域矩形的大小:

 

[java]
@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); 

@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移动行为。

[java] 
@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(); 
 } 

@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焦点。 “上”,“下”就

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,