Context として以下のように Application Context を渡しているコードを見かけました。
- public class MainActivity extends AppCompatActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Button textView = new Button(getApplicationContext());
- }
- }
View に渡された Context はスタイル属性を取得するのに使われます。
View.java
- public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- this(context);
- final TypedArray a = context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
- ...
- background = a.getDrawable(attr);
- ...
- 1. XMLタグで指定された値(例 android:background="@drawable/button_bg")
- 2. style で指定された値(例 style="@style/MyButtonStyle)
- 3. テーマで指定された値(例 テーマの中で
- @style/MyButtonStyle
)
このことを踏まえて obtainStyledAttributes() の中身をみると
Context.java
- public final TypedArray obtainStyledAttributes(
- AttributeSet set, @StyleableRes int[] attrs, @AttrRes int defStyleAttr,
- @StyleRes int defStyleRes) {
- return getTheme().obtainStyledAttributes(
- set, attrs, defStyleAttr, defStyleRes);
- }
つまり、3. では Context が持っているテーマ情報を使っているのです。
Application Context を渡してはいけない理由がわかったでしょうか。
Activity ごとにテーマを指定できるのに、Application Context を渡してしまうと、Activity のテーマが全く利用されません。
実際にやってみましょう。
Application には Theme.AppCompat(黒系)、MainActivity には Theme.AppCompat.Light(白系)を指定します。
- <manifest ...>
- <application
- ...
- android:theme="@style/Theme.AppCompat">
- <activity
- android:name=".MainActivity"
- android:theme="@style/Theme.AppCompat.Light">
- ...
- </activity>
- </application>
- </manifest>
- public class MainActivity extends AppCompatActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Button button1 = new Button(getApplicationContext());
- button1.setText("Application Context");
- Button button2 = new Button(this);
- button1.setText("Activity Context");
- LinearLayout ll = (LinearLayout) findViewById(R.id.container);
- ll.addView(button1);
- ll.addView(button2);
- }
- }

画面のテーマは Theme.AppCompat.Light (白系)なのに、Application Context を渡した上のボタンは Theme.AppCompat(黒系)の色になってしまっています。
Context が持つテーマが利用されるという仕組みは、v7 AppCompat Support Library でも使われています。 AppCompatTextView を見てみましょう。
- public class AppCompatTextView extends TextView implements TintableBackgroundView {
- ...
- public AppCompatTextView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(TintContextWrapper.wrap(context), attrs, defStyleAttr);
これにより、colorAccent の指定色によって自動でテキストカーソルなどが tint されます。
0 件のコメント:
コメントを投稿