カスタム字幕を表示するために、EditText サブクラスで onDraw をオーバーライドしようとしています。動作していますが、いくつかのバグがあります。
基本的に、私がする必要があるのは、ビューの左上隅から特定のオフセットで StaticLayout を描画することだけです。
残念ながら、onDraw メソッドで得られるのはキャンバスだけです。キャンバスのサイズは画面全体のサイズ (320x480 ディスプレイのデバイスでは 320x480) に等しく、そのクリップ境界はほぼ何でもかまいません - ビュー全体にすることができます。ビューがスクロールビュー内にあり、部分的に表示されている場合、ビューの上部または下部のみにすることができます。おそらくスーパークラスがその領域の一部のみを無効にするため、ビュー内で同じ任意の四角形にすることさえできます。
したがって、サイズが 320x48 のこのビューがある場合、サイズが 320x480 でクリッピング rect (200、200、300、230) (左、上、右、下) のキャンバスを取得できます。このクリッピング四角形がビュー座標にどのようにマッピングされるかわかりません。
ビューの左上隅に対するクリッピング四角形の左上隅がどこにあるかを知る必要があります。残念ながら、これを取得する方法がわかりません。
追加:
このコードは、私がテストしたすべての OS バージョンで動作します:
private int[] coordinates = new int[2];
private Matrix identityMatrix = new Matrix();
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
getLocationInWindow(coordinates);
canvas.setMatrix(identityMatrix);
canvas.translate(coordinates[0], coordinates[1]);
//do the drawing in EditText coordinate space
canvas.restore();
}
ただし、まだ 1 つの質問があります。なぜ機能するのでしょうか。
View クラスをオーバーライドしようとしましたが、onDraw メソッドは常に View 自体のサイズと一致するサイズのキャンバスを受け取ります。ダイレクト View サブクラスの Canvas には、クリッピング rect がありません。TextView (EditText クラスの直接の祖先) についても同じです。しかし、EditText は同じではありません。EditText の onDraw メソッドに渡されるキャンバスには、常に (またはそうでない?) 画面のサイズと、カスタム クリッピング rect があります。この「ウィンドウ内のビュー座標による変換」全体が非常にハックに思えます。座標空間を変換する必要がある理由がわかりません。
答えを得るためにAndroidのソースコードをハッキングしようとしましたが、何も見つかりませんでした。EditText には独自の onDraw はありません。理論的には、TextView onDraw のオーバーライドと EditText onDraw のオーバーライドに違いはないはずです。しかし、違いがあります。onDraw メソッドに渡されるキャンバス オブジェクトは、TextView か EditText かによって異なります。なんで?行列に変換を適用する必要がある場合と適用しない場合をどのように知ることができますか?