1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui; 16 17 import android.annotation.Nullable; 18 import android.content.Context; 19 import android.content.res.Configuration; 20 import android.content.res.TypedArray; 21 import android.os.LocaleList; 22 import android.util.AttributeSet; 23 import android.view.LayoutInflater; 24 import android.view.View; 25 import android.widget.FrameLayout; 26 27 import com.android.systemui.statusbar.policy.ConfigurationController; 28 29 import java.util.ArrayList; 30 import java.util.List; 31 32 /** 33 * Custom {@link FrameLayout} that re-inflates when changes to {@link Configuration} happen. 34 * Currently supports changes to density, asset path, and locale. 35 */ 36 public class AutoReinflateContainer extends FrameLayout implements 37 ConfigurationController.ConfigurationListener { 38 39 private final List<InflateListener> mInflateListeners = new ArrayList<>(); 40 private final int mLayout; 41 AutoReinflateContainer(Context context, @Nullable AttributeSet attrs)42 public AutoReinflateContainer(Context context, @Nullable AttributeSet attrs) { 43 super(context, attrs); 44 45 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoReinflateContainer); 46 if (!a.hasValue(R.styleable.AutoReinflateContainer_android_layout)) { 47 throw new IllegalArgumentException("AutoReinflateContainer must contain a layout"); 48 } 49 mLayout = a.getResourceId(R.styleable.AutoReinflateContainer_android_layout, 0); 50 a.recycle(); 51 inflateLayout(); 52 } 53 54 @Override onAttachedToWindow()55 protected void onAttachedToWindow() { 56 super.onAttachedToWindow(); 57 Dependency.get(ConfigurationController.class).addCallback(this); 58 } 59 60 @Override onDetachedFromWindow()61 protected void onDetachedFromWindow() { 62 super.onDetachedFromWindow(); 63 Dependency.get(ConfigurationController.class).removeCallback(this); 64 } 65 inflateLayoutImpl()66 protected void inflateLayoutImpl() { 67 LayoutInflater.from(getContext()).inflate(mLayout, this); 68 } 69 inflateLayout()70 public void inflateLayout() { 71 removeAllViews(); 72 inflateLayoutImpl(); 73 final int N = mInflateListeners.size(); 74 for (int i = 0; i < N; i++) { 75 mInflateListeners.get(i).onInflated(getChildAt(0)); 76 } 77 } 78 addInflateListener(InflateListener listener)79 public void addInflateListener(InflateListener listener) { 80 mInflateListeners.add(listener); 81 listener.onInflated(getChildAt(0)); 82 } 83 84 @Override onDensityOrFontScaleChanged()85 public void onDensityOrFontScaleChanged() { 86 inflateLayout(); 87 } 88 89 @Override onOverlayChanged()90 public void onOverlayChanged() { 91 inflateLayout(); 92 } 93 94 @Override onLocaleListChanged()95 public void onLocaleListChanged() { 96 inflateLayout(); 97 } 98 99 public interface InflateListener { 100 /** 101 * Called whenever a new view is inflated. 102 */ onInflated(View v)103 void onInflated(View v); 104 } 105 } 106