2016-06-13 50 views
2

我有一個很大的EditText用於輸入代碼。它可以水平滾動(故意嵌套在HorizontalScrollView中),並與ScrollView內的其餘頁面垂直滾動。我也有錯誤突出功能:當用戶按下預覽或保存,代碼驗證和錯誤使用BackgroundColorSpans這樣強調:以編程方式將EditText範圍滾動到視圖中

Editable text = mConfig.getText(); 
for (OverlayValidator.ValidationError error : errors) { 
    text.setSpan(
      new BackgroundColorSpan(error.isCritical ? 0x40FF0000 : 0x40FF8800), 
      error.errorStart, error.errorEnd, 
      Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_INTERMEDIATE 
    ); 
} 

現在我希望把重點放在任意的錯誤,即滾動它到如果屏幕當前不在屏幕上,則顯示屏幕。此在計算器上一種廣泛建議的解決方案是迫使在期望範圍內的選擇:

Selection.setSelection(mConfig.getText(), errors.get(0).errorStart, errors.get(0).errorEnd); 

這確實有效,並且該範圍滾動本身到視圖(video here),然而,如上錫說,它突出範圍,這是不可取的。

我可以通過指定只有一個位置,將光標,這樣

Selection.setSelection(mConfig.getText(), errors.get(0).errorEnd); 

避免選擇但這隻會確保光標進入屏幕,並且該範圍的其餘部分可保持摘屏幕(another video)。

試圖撥打這兩個結果只有最後選擇命令生效,即使我打電話給他們這樣的:

Selection.setSelection(mConfig.getText(), errors.get(0).errorStart, errors.get(0).errorEnd); 
Handler handler = new Handler(); 
handler.post(new Runnable() { 
    @Override 
    public void run() { 
     Selection.setSelection(mConfig.getText(), errors.get(0).errorEnd); 
    } 
}); 

基本上我需要Selection的副作用沒有實際的選擇(滾動到視圖)。

我試圖檢查代碼,以瞭解如何在屏幕上召喚選定範圍,但代碼太糾結(跨度,觀察者和所有這些東西),我無法弄清楚。從文檔中我遇到了方法View.requestRectangleOnScreen(Rect),但是我如何獲得rect滾動到? (我總是可以採取TextPaint自己測量字符,但必須有更好的方法!)

謝謝。

回答

0

其實我當時解決了它,但忘了發佈答案。

您可以通過在TextView的Layout對象上調用getSelectionPath(start, end, outPath)來獲得所需子字符串的座標,然後請求這些對象的焦點。例如,我分類爲TextView並添加了此方法:

// ...  
private Path mTempPath = new Path(); 
private RectF mTempRectF = new RectF(); 
private Rect mTempRect = new Rect(); 
// ... 

public void requestFocusRange(int start, int end) { 
    final Layout layout = getLayout(); 
    if (layout == null) { 
     // probably rotating the screen, do nothing 
     return; 
    } 

    layout.getSelectionPath(start, end, mTempPath); 
    mTempPath.computeBounds(mTempRectF, false); 
    mTempRectF.roundOut(mTempRect); 

    // Fix the coordinates origin 
    final int paddingLeft = getTotalPaddingLeft(); 
    mTempRect.offset(paddingLeft, getTotalPaddingTop()); 

    // Unnecessary - I'm just adding extra spacing to the focused rect 
    mTempRect.inset(-paddingLeft, -paddingLeft); 

    requestRectangleOnScreen(mTempRect, false); 
} 
相關問題