TermsListAdapter.java revision 409de097fb94e4ecf05fa582140ae01d1c54f49e
1/*
2 * Copyright 2016, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.managedprovisioning.preprovisioning.terms;
17
18import static com.android.internal.util.Preconditions.checkNotNull;
19
20import android.text.Spanned;
21import android.text.method.LinkMovementMethod;
22import android.view.LayoutInflater;
23import android.view.View;
24import android.view.ViewGroup;
25import android.view.accessibility.AccessibilityNodeInfo;
26import android.widget.BaseExpandableListAdapter;
27import android.widget.ImageView;
28import android.widget.TextView;
29
30import com.android.managedprovisioning.R;
31import com.android.managedprovisioning.common.HtmlToSpannedParser;
32
33import java.util.List;
34
35/**
36 * Allows for displaying {@link TermsDocument} objects in an
37 * {@link android.widget.ExpandableListView}.
38 */
39class TermsListAdapter extends BaseExpandableListAdapter {
40    private final List<TermsDocument> mTermsDocuments;
41    private final LayoutInflater mInflater;
42    private final HtmlToSpannedParser mHtmlToSpannedParser;
43    private final GroupExpandedInfo mGroupExpandedInfo;
44
45    /**
46     * Creates a new instance of the class.
47     */
48    TermsListAdapter(List<TermsDocument> termsDocuments, LayoutInflater layoutInflater,
49            HtmlToSpannedParser htmlToSpannedParser, GroupExpandedInfo groupExpandedInfo) {
50        mTermsDocuments = checkNotNull(termsDocuments);
51        mInflater = checkNotNull(layoutInflater);
52        mHtmlToSpannedParser = checkNotNull(htmlToSpannedParser);
53        mGroupExpandedInfo = checkNotNull(groupExpandedInfo);
54    }
55
56    @Override
57    public int getGroupCount() {
58        return mTermsDocuments.size();
59    }
60
61    @Override
62    public int getChildrenCount(int groupPosition) {
63        return 1; // one content piece per header
64    }
65
66    @Override
67    public TermsDocument getGroup(int groupPosition) {
68        return getDisclaimer(groupPosition);
69    }
70
71    @Override
72    public TermsDocument getChild(int groupPosition, int childPosition) {
73        return getDisclaimer(groupPosition);
74    }
75
76    @Override
77    public long getGroupId(int groupPosition) {
78        return groupPosition;
79    }
80
81    @Override
82    public long getChildId(int groupPosition, int childPosition) {
83        return childPosition;
84    }
85
86    @Override
87    public boolean hasStableIds() {
88        return true;
89    }
90
91    // TODO: encapsulate this logic - too much direct view manipulation
92    @Override
93    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
94            ViewGroup parent) {
95        String heading = getDisclaimer(groupPosition).getHeading();
96
97        View groupView = convertView != null ? convertView : mInflater.inflate(
98                R.layout.terms_disclaimer_header, parent, false);
99        groupView.setContentDescription(
100                parent.getResources().getString(R.string.section_heading, heading));
101        groupView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
102            @Override public void onInitializeAccessibilityNodeInfo(View host,
103                    AccessibilityNodeInfo info) {
104                super.onInitializeAccessibilityNodeInfo(host, info);
105                info.addAction(new AccessibilityNodeInfo.AccessibilityAction(
106                        AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.getId(),
107                        parent.getResources().getString(
108                                isExpanded ? R.string.collapse : R.string.expand)));
109            }
110        });
111
112        TextView textView = groupView.findViewById(R.id.header_text);
113        textView.setText(heading);
114
115        ImageView chevron = groupView.findViewById(R.id.chevron);
116        chevron.setRotation(isExpanded ? 90 : -90); // chevron down / up retrospectively
117        groupView.findViewById(R.id.divider).setVisibility(
118                shouldShowGroupDivider(groupPosition) ? View.VISIBLE : View.INVISIBLE);
119
120        return groupView;
121    }
122
123    /**
124     * Helps avoid a double thick divider line: one above header, one from the bottom of prev child
125     */
126    private boolean shouldShowGroupDivider(int groupPosition) {
127        return mGroupExpandedInfo.isGroupExpanded(groupPosition)
128                && (groupPosition == 0 || !mGroupExpandedInfo.isGroupExpanded(groupPosition - 1));
129    }
130
131    // TODO: encapsulate this logic - too much direct view manipulation
132    @Override
133    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
134            View convertView, ViewGroup parent) {
135        View view = convertView != null ? convertView : mInflater.inflate(
136                R.layout.terms_disclaimer_content, parent, false);
137
138        TermsDocument disclaimer = getDisclaimer(groupPosition);
139        TextView textView = view.findViewById(R.id.disclaimer_content);
140        Spanned content = mHtmlToSpannedParser.parseHtml(disclaimer.getContent());
141        textView.setText(content);
142        textView.setContentDescription(
143                parent.getResources().getString(R.string.section_content, disclaimer.getHeading(),
144                        content));
145        textView.setMovementMethod(LinkMovementMethod.getInstance()); // makes html links clickable
146
147        return view;
148    }
149
150    private TermsDocument getDisclaimer(int index) {
151        return mTermsDocuments.get(index);
152    }
153
154    @Override
155    public boolean isChildSelectable(int groupPosition, int childPosition) {
156        return false;
157    }
158
159    interface GroupExpandedInfo {
160        boolean isGroupExpanded(int groupPosition);
161    }
162}