3

LinearLayout私は、拡張するカスタムビューTextView(これを「IdiomView」と呼び始めます)とを含む単純なものを持っていListViewます。IdiomView通常との唯一の違いは、テキストの長さが3行未満になるまで、テキストサイズを繰り返し縮小するメソッドをTextViewオーバーライドしたことです。onDraw()私の問題は、ビューが描画されると、ユーザーに次のように表示されることです。

 ______________
|__ACTION_BAR__|
|  IdiomView   |
|______________|
|              |
|   ListView   |
|              |
|              |
|______________|

これはすぐになります:

 ______________
|__ACTION_BAR__|
|__IdiomView __|
|              |
|   ListView   |
|              |
|              |
|              |
|______________|

IdiomViewつまり、ListViewが描画され、サイズが分類された後にジャンプアップします。

私が欲しいのはIdiomView、ListViewを描画する前に、完全に描画されるまで待つ方法です。この投稿すべてのビューが完全に描画された後に発生するイベントは何ですか?を呼び出して、描画が完了した後にスレッドを整列させる方法を説明しますView.post(Runnable)。問題は、小さいテキストが3行未満であるかどうかを計算するために、オーバーライドされたonDraw()メソッド呼び出しが複数回呼び出されることです。したがって、この要素は、表示する前に何度も「描画を終了」する可能性があります。onDraw()ListView

すべてのコメントと回答に感謝します。これが私の現在のコードです:

レイアウトXML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="10dp"
    android:background="@color/off_white"
    android:orientation="vertical" >

    <carter.cwords.idioms.IdiomView
        android:id="@+id/idiom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginBottom="10dp"
        android:textColor="@color/transparent"
        android:textSize="28sp"
        android:textStyle="italic"
        android:visibility="invisible" />

    <ListView
        android:id="@+id/quote_list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:choiceMode="none"
        android:footerDividersEnabled="false"
        android:headerDividersEnabled="false"
        android:visibility="invisible" />

</LinearLayout>

アクティビティ:

private IdiomView mIdiomTextView;
private ListView mQuoteList;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.idiom_of_the_day);
    mIdiomTextView = (IdiomView) findViewById(R.id.idiom);
    mQuoteList = (ListView) findViewById(R.id.quote_list);      

    // Populate page data onResume()
}

@Override
protected void onResume() {
    super.onResume();

    sendRequest(R.string.url_idiom_of_the_day, new AfterRequest(){
        @Override
        public void useResults(Document resultXml) {
            if(resultXml != null){

                Log.i(getClass().getSimpleName(), "useResults()");

                String idiomString = XmlUtilities.getTextValue(resultXml, NetworkHelper.XML_TAG_IDIOM_CONTENT);

                logDebug("idiomString: " + idiomString);
                mIdiomTextView.setText("\"" + idiomString + "\"");
                mQuoteList.setAdapter(new ContentAdapter(mContext, resultXml));
                mIdiomTextView.setVisibility(View.VISIBLE);

                mIdiomTextView.post(new Runnable(){
                    @Override
                    public void run() {
                        mQuoteList.setVisibility(View.VISIBLE);
                    }
                });
            }

        }
    });

}

IdiomView

public class IdiomView extends TextView {

    public IdiomView(Context context) {     
        super(context);
    }

    public IdiomView(Context context, AttributeSet attrs){
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.i(getClass().getSimpleName(), "onDraw(): " + this.getLineCount());
        if(this.getLineCount() > 2){
            this.setTextSize(TypedValue.COMPLEX_UNIT_PX, this.getTextSize()-1);
        }
        else{
            this.setTextColor(getResources().getColor(R.color.text));
        }
        Log.i(getClass().getSimpleName(), "onDraw(): " + this.getLineCount());

    }


}

どうもありがとうございます。

4

2 に答える 2

3

私はこれまでこれを試したことがありませんが、が描画された後、Viewアプリがでのみ動作するように指示するのに役立つと思います。リスナーを使用してこれを実現できる場合があります。ただし、コードビハインドメソッドを使用する必要があります。ListViewIdiomView

IdiomView次のようなインターフェイスを作成します

public static interface OnDrawComplete {
    public abstract void onDrawComplete();
}

private OnDrawComplete mListener;

public IdiomView(Context context) {     
    super(context);
    // this forces it to make sure it's actually an activity
    // context so you can get a listener
    if (context instanceof Activity)
        this.mListener = context;
}

図面の最後で、それを呼び出します

if (this.mListener != null)
    this.mListener.onDrawComplete();

これにより、オブジェクトを作成したアクティビティが呼び出され、オブジェクトの描画が通知されます。したがって、アクティビティ内で、インターフェイスを実装します

public void onDrawComplete() {
    // After the draw completes, it calls this callback.
    // setup the rest of your layout now
    mQuoteList = (ListView) findViewById(R.id.quote_list);
    this.populateQuoteList();
}

this.mListener.onDrawComplete();他のイベントで電話をかけることもできるかもしれViewませんが、適切なイベントが見つかりません。あなたはView.post(runnable)、それがうまくいくかもしれないと言いますが、私もそのようなものを使ったことがありません。

最大の潜在的な問題は、がどのようにコンテキストを受け取るのか、またはどのコンテキストを受け取るのかがわからないことIdiomViewです。この場合Activity、インターフェースを実装しているもののコンテキストが必要です。

適切なコンテキストが得られない場合は、このメソッドを使用するために、インスタンス化してレイアウトに手動で追加する必要がある可能性があります。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mIdiomTextView = new mIdiomTextView(this);
    // add to the Layout manually.  
}

ここにそれのより多くが肉付けされています

IdiomView

public class IdiomView extends TextView {
    public static interface OnDrawComplete {
        public abstract void onDrawComplete();
    }

    private OnDrawComplete mListener;

    public IdiomView(Context context) {     
        this(context, 0);
    }

    public IdiomView(Context context, AttributeSet attrs){
        super(context, attrs);
        if (context instanceof Activity)
            this.mListener = context;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // do your drawing code here
        // ...
        // after drawing, call the listener, which tells your
        // Activity to deal with the ListView.
        if (this.mListener != null)
            this.mListener.onDrawComplete();
    }
}

アクティビティ

public class MyActivity extends Activity implements IdiomView.OnDrawComplete {
    //...

    private IdiomView mIdiomTextView;
    private ListView mQuoteList;

    public void onDrawComplete() {
        // After the draw completes, it calls this callback.
        // setup the rest of your layout now
        mQuoteList = (ListView) findViewById(R.id.quote_list);
        this.populateQuoteList();
        // now show the ListView
        mQuoteList.setVisibility(View.Visible);
    }

    private void populateQuoteList() {
        // populate your ListView here
    }
}
于 2013-02-20T21:25:29.860 に答える
2

適切なフォントサイズが見つかるまでテキストサイズを繰り返し設定するTextViewと、毎回再測定して再描画する必要があるため、非常に非効率になる可能性があります。TextView.getPaint()これを行う代わりに、そのメソッドを使用してテキストを1回だけ測定および設定できます。によって返される値がウィジェットの現在の幅の2倍を下回るPaintまで、さまざまなフォントサイズを提供するループ内でテキストを測定することができます。Paint.measureText()

于 2013-02-22T05:18:57.583 に答える