-1

編集:カスタムビューを作成し、それを使用せずにビューを更新しようとしたときに、重要な概念であるメッセージキューが欠落していたことが、問題の原因であることが判明しました。これはここで解決されます:

Android:メッセージキューをサポートするカスタムビューの作成

OnCreateが終了した後(「通常のように」)、runtime / androidがOnMeasureを呼び出せるようにする必要があり、その間に.postメソッドを介してメッセージキューのビューに更新を配置する必要があります。

したがって、通常どおりOnCreateでFindViewByIdを介してビューへのハンドルを取得し、ランナブル内で(setTextなどのオーバーライドまたは独自のset関数を介して)更新を投稿できます(上記のリンクを参照)。


私はかなり長い間Androidでカスタムビューに取り組んでおり、コンストラクター、属性、レイアウトパラメーター、および描画メソッド(OnMeasure、OnLayoutなど)を徹底的に実験してきました。

最も親のビューグループ(レンダリング用にレイアウトファイルで宣言されたもの)はRelativeLayoutを継承し、3つの子ビュー、すべてのカスタム/継承されたビューグループなどを含みます。

私はカスタムカレンダーを実装しています(私は知っています、非常に独創的でエキサイティングです)、CustomCalendarと呼びます。だから、私のレイアウトファイルにはステートメントがあります

<MonoDroid.CustomViews.CustomCalendar
  xmlns:calendar="http://schemas.android.com/apk/res/net.monocross.appname"
  android:id="+id/Calendar1"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  calendar:row_count="5"
  calendar:col_count="7"
 ...
/>

このビューは、レイアウトファイルで定義されている他のいくつかのビューと一緒に存在するため、これから説明する複雑な問題の原因になります。

OnMeasureが呼び出される前にこのビューの寸法を取得する方法を理解しようとしています(問題はありませんが、子ビューのレイアウト寸法はこのビューの寸法から決定されるため、子ビューをインスタンス化するには、初めてOnMeasureが呼び出され、これは必要になった後、OnCreateが終了した後であることがわかります。

つまり、OnCreateでSetContentViewを呼び出し、FindViewById(Resource.Id.Calendar1)を介してカスタムビューをインスタンス化した後、OnMeasureオーバーライド(ここでもb / c OnMeasure)から実行された場合、子ビューもインスタンス化されません。 OnCreateが戻るまで呼び出されません)。

コンストラクターに渡された属性を読み取ると、layout_widthとlayout_heightから取得するすべてがfill_parentの定数-1になります。補正するビューが他にもあるので、画面全体を使用することもできません。


したがって、コンストラクター内からカスタムビューのディメンションを決定するための最良のアプローチを探しています。これにより、ビューの子孫すべてを適切なレイアウトディメンションでインスタンス化して、ビューを次の場所から利用できるようにすることができます。 SetContentViewが呼び出された後、OnCreateから戻る前のOnCreate(コンテンツで更新するため)。

同じ目的を達成するための別の手段は私にとっては問題ありませんが、インフラストラクチャが意図する方法でこれを実行することを検討しています(そのようなことがある場合)。

4

3 に答える 3

1

コンストラクターでディメンションを取得することはできません。せいぜい、それらがXMLで定義されている場合、属性セットからレイアウトの幅と高さを取得できます。

あなたがすべきことは、onMeasureとonLayoutをオーバーライドすることです。onMeasureで必要な計算と設定を実行してから、計算値をに渡すことができますmeasureChild(view, widthSpec, heightSpec)。そして、onLayoutでレイアウトをいじってから、を呼び出すことができますchildView.layout(left, top, right, bottom)

于 2012-10-16T21:08:19.837 に答える
1

私はこの問題を抱えていたと思います。自分でタイミングはわかりませんが、寸法を出すために次のようにしました

ViewTreeObserver viewTreeObserver = mOverlayFrameLayout.getViewTreeObserver();
                if (viewTreeObserver.isAlive()) {
                  viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                    public void onGlobalLayout() {
                        mOverlayFrameLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                        //do some things
                    }
                  });
                }
于 2012-10-16T21:10:54.643 に答える
0

編集これを行わないでください(OPの編集ノートを参照)。


結局、onMeasureがこの問題を解決する場所です...

Yaは、OnCreateからビューでMeasureを呼び出す必要があります。これには、Measureが使用する幅と高さのMeasureSpecパラメーターを作成する必要があります。

public class Activity1 : Activity
{
    ...

    private CustomCalendar _calendar;

    public override void OnCreate()
    {
        SetContentView(Resource.Layout.Calendar);

        _calendar = FindViewById<CustomCalendar>(Resource.Id.Calendar1);           

        int widthMeasureSpec = View.MeasureSpec.MakeMeasureSpec(Resources.DisplayMetrics.WidthPixels, MeasureSpecMode.Exactly);
        int heightMeasureSpec = View.MeasureSpec.MakeMeasureSpec(Resources.DisplayMetrics.HeightPixels, MeasureSpecMode.Exactly);

        _calendar.Measure(widthMeasureSpec, heightMeasureSpec);

        ...
    }
}

次に、すべてのネストされた/子ビューに対して同じことを再帰的に実行します。

各カスタムビューに静的bool変数があり、ビューが初期化されているかどうかを追跡し、onMeasureでチェックして、初期化して測定する必要があるかどうかを判断します。

    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        base.OnMeasure(widthMeasureSpec, heightMeasureSpec);

        if (!_initialized)
        {
            _WIDTH = MeasureSpec.GetSize(widthMeasureSpec);
            _HEIGHT = MeasureSpec.GetSize(heightMeasureSpec);

            InitViews();

            MeasureSpecMode widthMode = MeasureSpec.GetMode(widthMeasureSpec);
            MeasureSpecMode heightMode = MeasureSpec.GetMode(heightMeasureSpec);

            widthMeasureSpec = MeasureSpec.MakeMeasureSpec(_childView.LayoutParameters.Width, widthMode);
            heightMeasureSpec = MeasureSpec.MakeMeasureSpec(_childView.LayoutParameters.Height, heightMode);

            _childView.Measure(widthMeasureSpec, heightMeasureSpec);

            _initialized = true;
        }
    }
于 2012-10-17T18:01:03.883 に答える