

Androidにて複数のViewをまとめて１つのViewとして扱うことはできますか？

例えば以下の概形で表されるようなレイアウトがあるとします。

[code]

    <!-- layout/my_view.xml(概形) -->
    <LinearLayout>
        <TextView android:id="@+id/title" />
        <TextView android:id="@+id/content" />
    </LinearLayout>
    
[/code]

そしてこのルートであるLinearLayoutを継承したMyViewがあるとします

[code]

    class MyView extends LinearLayout {
        TextView titleTV, contentTV;
    
        //コンストラクタもろもろ
    
        public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            View root = LayoutInflater.from(context).inflate(R.layout.my_view, this);
            titleTV = root.findViewById(R.id.title);
            contentTV = root.findViewById(R.id.content);
    
            //TypedArrayなどもろもろ
        }
    
        public void setTitle(String title) {
            titleTV.setText(title);
        }
    
        //以下メソッドもろもろ
    }
    
[/code]

これを利用するActivityが次のようにあるとします  
レイアウトファイル

[code]

    <!-- layout/activity_main.xml(概形) -->
    <LinearLayout>
        <***.***.MyView android:id="@+id/my_view_1" />
        <***.***.MyView android:id="@+id/my_view_2" />
    </LinearLayout>
    
[/code]

クラス

[code]

    class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.oncreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            View view = findViewById(R.id.my_view_1);
            // view instanceof LinearLayout となってしまい以下のようにできない
    
            MyView myView = (MyView)findViewById(R.id.my_view_2); //キャスト不可で落ちる
            myView.setTitle("タイトル");
        }
    }
    
[/code]

コード内に書いた通り、findViewbyIdで取得したインスタンスがルートのインスタンスとなってしまい、肝心のメソッドを使用することができません。  
心当たりとしてLinearLayoutを継承したことが挙げられますが、代わりにViewを継承するとViewがViewGroupでないため、inflateの引数と一致しなくなってしまい困っています

[code]

    class MyView extends View {
        public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
            View root = LayoutInflater.from(context).inflate(R.layout.my_view, this);
            // thisがViewGroupでないので×
    
            View root = LayoutInflater.from(context).inflate(R.layout.my_view, null);
            // 実行時にエラーが発生し×
        }
    }
    
[/code]

なお`<merge>`で囲うとよいというQ&AやDevelopersBlogを見ましたが、上記の問題によりうまく解決しませんでした。  
どのようにすればCustomViewのインスタンスを取得できるのでしょうか？

/* 追記 */

まずは解決したことを報告させていただきます。(腑には落ちていないですが...)  
1について  
・今回はクラスに問題があると考え階層構造が分かる最低限を抜粋しました  
2について  
・内部でthis(context, attrs, defStyleAttr)を呼ぶだけであったので省略しました  
3について  
・API Level 26を使用していたため総称型により明示的なcastを省略しました

いずれについても詳細を記述するべきでした

Android Studio Previewでプログラムを組んでいたためAndroid Studio 2.6で書き直したところ正常に機能しました。  
そこで再びPreview版でエラーを確認するために実行したところ今度は何故かすんなりと正常に実行されました。  
よく分かりませんが解決はしました。  
エラーが発生してから正常に実行されるまで該当箇所は書き換えておらず、何故急に型が変わったのか不明です。


CC BY-SA 3.0
2017-09-08T08:42:50.027
37807
2020-02-10T09:01:40.200
2017-09-08T11:40:22.133
6055
6055
question
android android-layout
CustomViewのインスタンスを取得するには


これでできるはず

[code]

    MyView myView = (MyView)findViewById(R.id.my_view_1);
    myView.setTitle("タイトル");
    
[/code]


CC BY-SA 3.0
2017-09-08T09:06:00.827
37808
2017-09-08T09:06:00.827
21081
37807
answer


急ぎで書かれたのだと思いますが、いくつか記述がミスがあるように見受けます。

  1. my_view.xmlなどのレイアウトファイルに必須のattributeが不足している(layout_width、layout_height)
  2. カスタムViewであるMyViewのコンストラクタが足りていない(defStyleAttrのないものです)
  3. 各種Viewへのキャストがない(`titleTV = (TextView)root.findViewById(R.id.title);`)

それ以外ですと、ログを貼り付けた方がより正確な回答ができると思います。

ちなみに、Viewを継承しているクラスは`#inflate(Context, int,
ViewGroup)`が利用できますので(内部的に同じことをしているだけですが…)、ご参考までに。


CC BY-SA 3.0
2017-09-08T09:19:22.207
37809
2017-09-08T09:19:22.207
22792
37807
answer