27

本を表示するアプリケーションを開発しています。本を表示する画面(Activity)があります。ViewSwitcher に似たカスタム ビューがあり、すべてのページはカスタム ビューによってレンダリングされるビットマップです。

次に、アクセシビリティ機能を実装する必要があります-本は電話で読む必要があります(オーディオ)。

ここでアクセシビリティセクションを読みましたhttps://developer.android.com/guide/topics/ui/accessibility/index.htmlしかし、十分に明確ではありません。

アクセシビリティ管理に SupportLibrary を使用しており、このコードを ViewGroup (本のページを管理する) に持っています。コード 1 :

private class EditionPagesViewSwitcherAccessibilityDelegate extends AccessibilityDelegateCompat {

    private int mPageCount;
    private double[] mPageRange;

    @Override
    public void onInitializeAccessibilityEvent(final View host, final AccessibilityEvent event) {
        super.onInitializeAccessibilityEvent(host, event);
        event.setClassName(EditionPagesViewSwitcher.class.getName());
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            event.setScrollable(canScroll());
        }
        if (event.getEventType() == AccessibilityEventCompat.TYPE_VIEW_SCROLLED && updatePageValues()) {
            event.setItemCount(mPageCount);
            // we use +1 because of user friendly numbers (from 1 not 0)
            event.setFromIndex((int) (mPageRange[0] + 1));
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                event.setToIndex((int) (mPageRange[1] + 1));
            }
        }
    }

    @Override
    public void onInitializeAccessibilityNodeInfo(final View host, final AccessibilityNodeInfoCompat info) {
        super.onInitializeAccessibilityNodeInfo(host, info);
        info.setClassName(EditionPagesViewSwitcher.class.getName());

        info.setScrollable(canScroll());
        info.setLongClickable(true);
        if (canScrollForward()) {
            info.addAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD);
        }
        if (canScrollBackward()) {
            info.addAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD);
        }
    }

    @Override
    public boolean performAccessibilityAction(final View host, final int action, final Bundle args) {
        if (super.performAccessibilityAction(host, action, args)) {
            return true;
        }
        switch (action) {
            case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD: {
                if (canScrollForward()) {
                    showNext();
                    return true;
                }
            }
            return false;
            case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD: {
                if (canScrollBackward()) {
                    showPrevious();
                    return true;
                }
            }
            return false;
        }
        return false;
    }

ページ ビューコード 2のコードは次のとおりです。

    @Override
    public void onInitializeAccessibilityEvent(final View host, final AccessibilityEvent event) {
        super.onInitializeAccessibilityEvent(host, event);

        event.setClassName(EditionPageView.class.getName());
        if (hasText()) {
            event.getText().add(getPageRangeText());
            final String trimText = mSurfaceUpdateData.getPageText().trim();
            if (trimText.length() > MAX_TEXT_LENGTH) {
                event.getText().add(trimText.substring(0, MAX_TEXT_LENGTH));
//              event.getText().add(trimText.substring(MAX_TEXT_LENGTH, trimText.length()));
            }
            else {
                event.getText().add(trimText);
            }
        }
    }

    @Override
    public void onInitializeAccessibilityNodeInfo(final View host, final AccessibilityNodeInfoCompat info) {
        super.onInitializeAccessibilityNodeInfo(host, info);

        info.setClassName(EditionPageView.class.getName());
    }

ページのテキスト データは初めて非同期で読み込まれるため、 onInitializeAccessibilityEvent コードの実行中にテキストがありません。そして、データがロードされたら、AccessibilityEvent.TYPE_VIEW_SELECTED および AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED イベントを発生させます。次に、 onInitializeAccessibilityEvent が再度実行され、電話で本のテキストを「読み上げ」ます。

だから私の質問:

  1. アクセシビリティの実装は正しいですか? もしかして設計ミス?この機能に関する適切なチュートリアルが見つからなかったためです。
  2. コード 1 のサポート実装で SDK バージョン チェックを使用する必要があるのはなぜですか? サポートの実装が正しく処理しないのはなぜですか?
  3. TYPE_VIEW_SELECTED と TYPE_VIEW_TEXT_CHANGED の起動は本当に必要ですか? それとも、他のコードを実装する必要があるのでしょうか?
  4. 主な質問。コード 2 には、コメント化されたコード行があります。このコード ステートメントの部分文字列のテキストは、MAX_TEXT_LENGTH (3800) より小さくなります。これよりも大きいテキストは何も再生されないためです。何もない。アクセシビリティ制限ですか?この値より小さい他のテキストは適切に再生されます。
  5. 良いチュートリアルがどこにあるか知っている人はいますか? (はい、サンプルを見ました)。
  6. 誰かが見るべきカスタム実現を持っていますか?

更新しました

良い。ここにいくつかの答えがあります:

  1. TYPE_VIEW_SELECTED および TYPE_VIEW_TEXT_CHANGED イベントは、このテキストを取得したらすぐに読みたくない場合は必要ありません。
  2. Nexus 7 ではすべての大きなテキスト (最大 8000 シンボルのテキスト) が適切に再生されるため、この問題は再現されませんが、Samsung Galaxy Tab 10.1 (Android 4.0.4) および Android 4.3 を搭載した Tab 10.1 の Genymotion エミュレーターでは再現されます。そして、これは奇妙です...
4

2 に答える 2

1

4.. のドキュメントによると、String.substring() 渡す最初の引数は元の文字列の開始インデックスであり、2 番目の引数は元の文字列の終了インデックスです。

例:

String text = "Hello";
partOfText = text.substring(2,text.length() - 1);

partOfText「llo」に等しい (最初の文字はインデックス 0)

したがって、定数MAX_TEXT_LENGTHを最初の引数として配置すると、インデックス 3800 から部分文字列が取り出されます。

http://developer.android.com/reference/java/lang/String.html#substring(int)

于 2013-12-17T15:41:47.543 に答える
0

MAX_TEXT_LENGTH は 3800 です。

あなたの疑いについて、

このコード:

 event.getText().add(trimText.substring(MAX_TEXT_LENGTH, trimText.length()));
        }

「trimText」を MAX_TEXT_LENGTH から trimText.length() にサブストリング化しようとしています! trimText = "STACK"、trimText.length() = 5 とすると、trimText.substring(3800,5) は ?

最初は意味がありません。正しく使用すると次のようになります。

于 2014-07-15T17:54:06.583 に答える