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 java.util.ArrayList; 28 import java.util.List; 29 30 /** 31 * Custom {@link FrameLayout} that re-inflates when changes to {@link Configuration} happen. 32 * Currently supports changes to density and locale. 33 */ 34 public class AutoReinflateContainer extends FrameLayout { 35 36 private final List<InflateListener> mInflateListeners = new ArrayList<>(); 37 private final int mLayout; 38 private int mDensity; 39 private LocaleList mLocaleList; 40 AutoReinflateContainer(Context context, @Nullable AttributeSet attrs)41 public AutoReinflateContainer(Context context, @Nullable AttributeSet attrs) { 42 super(context, attrs); 43 44 mDensity = context.getResources().getConfiguration().densityDpi; 45 mLocaleList = context.getResources().getConfiguration().getLocales(); 46 47 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoReinflateContainer); 48 if (!a.hasValue(R.styleable.AutoReinflateContainer_android_layout)) { 49 throw new IllegalArgumentException("AutoReinflateContainer must contain a layout"); 50 } 51 mLayout = a.getResourceId(R.styleable.AutoReinflateContainer_android_layout, 0); 52 inflateLayout(); 53 } 54 55 @Override onConfigurationChanged(Configuration newConfig)56 protected void onConfigurationChanged(Configuration newConfig) { 57 super.onConfigurationChanged(newConfig); 58 boolean shouldInflateLayout = false; 59 final int density = newConfig.densityDpi; 60 if (density != mDensity) { 61 mDensity = density; 62 shouldInflateLayout = true; 63 } 64 final LocaleList localeList = newConfig.getLocales(); 65 if (localeList != mLocaleList) { 66 mLocaleList = localeList; 67 shouldInflateLayout = true; 68 } 69 70 if (shouldInflateLayout) { 71 inflateLayout(); 72 } 73 } 74 inflateLayoutImpl()75 protected void inflateLayoutImpl() { 76 LayoutInflater.from(getContext()).inflate(mLayout, this); 77 } 78 inflateLayout()79 protected void inflateLayout() { 80 removeAllViews(); 81 inflateLayoutImpl(); 82 final int N = mInflateListeners.size(); 83 for (int i = 0; i < N; i++) { 84 mInflateListeners.get(i).onInflated(getChildAt(0)); 85 } 86 } 87 addInflateListener(InflateListener listener)88 public void addInflateListener(InflateListener listener) { 89 mInflateListeners.add(listener); 90 listener.onInflated(getChildAt(0)); 91 } 92 93 public interface InflateListener { 94 /** 95 * Called whenever a new view is inflated. 96 */ onInflated(View v)97 void onInflated(View v); 98 } 99 } 100