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
15package com.android.systemui;
16
17import android.annotation.Nullable;
18import android.content.Context;
19import android.content.res.Configuration;
20import android.content.res.TypedArray;
21import android.os.LocaleList;
22import android.util.AttributeSet;
23import android.view.LayoutInflater;
24import android.view.View;
25import android.widget.FrameLayout;
26
27import com.android.systemui.statusbar.policy.ConfigurationController;
28
29import java.util.ArrayList;
30import 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 */
36public class AutoReinflateContainer extends FrameLayout implements
37        ConfigurationController.ConfigurationListener {
38
39    private final List<InflateListener> mInflateListeners = new ArrayList<>();
40    private final int mLayout;
41
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
55    protected void onAttachedToWindow() {
56        super.onAttachedToWindow();
57        Dependency.get(ConfigurationController.class).addCallback(this);
58    }
59
60    @Override
61    protected void onDetachedFromWindow() {
62        super.onDetachedFromWindow();
63        Dependency.get(ConfigurationController.class).removeCallback(this);
64    }
65
66    protected void inflateLayoutImpl() {
67        LayoutInflater.from(getContext()).inflate(mLayout, this);
68    }
69
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
79    public void addInflateListener(InflateListener listener) {
80        mInflateListeners.add(listener);
81        listener.onInflated(getChildAt(0));
82    }
83
84    @Override
85    public void onDensityOrFontScaleChanged() {
86        inflateLayout();
87    }
88
89    @Override
90    public void onOverlayChanged() {
91        inflateLayout();
92    }
93
94    @Override
95    public void onLocaleListChanged() {
96        inflateLayout();
97    }
98
99    public interface InflateListener {
100        /**
101         * Called whenever a new view is inflated.
102         */
103        void onInflated(View v);
104    }
105}
106