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 */ 16 package com.android.managedprovisioning.preprovisioning.terms; 17 18 import static com.android.internal.util.Preconditions.checkNotNull; 19 20 import android.text.Spanned; 21 import android.text.method.LinkMovementMethod; 22 import android.view.LayoutInflater; 23 import android.view.View; 24 import android.view.ViewGroup; 25 import android.view.accessibility.AccessibilityNodeInfo; 26 import android.widget.BaseExpandableListAdapter; 27 import android.widget.ImageView; 28 import android.widget.TextView; 29 30 import com.android.managedprovisioning.R; 31 import com.android.managedprovisioning.common.AccessibilityContextMenuMaker; 32 import com.android.managedprovisioning.common.HtmlToSpannedParser; 33 34 import java.util.List; 35 36 /** 37 * Allows for displaying {@link TermsDocument} objects in an 38 * {@link android.widget.ExpandableListView}. 39 */ 40 class TermsListAdapter extends BaseExpandableListAdapter { 41 private final List<TermsDocument> mTermsDocuments; 42 private final LayoutInflater mInflater; 43 private final HtmlToSpannedParser mHtmlToSpannedParser; 44 private final AccessibilityContextMenuMaker mContextMenuMaker; 45 private final GroupExpandedInfo mGroupExpandedInfo; 46 47 /** 48 * Creates a new instance of the class. 49 */ 50 TermsListAdapter(List<TermsDocument> termsDocuments, LayoutInflater layoutInflater, 51 AccessibilityContextMenuMaker contextMenuMaker, HtmlToSpannedParser htmlToSpannedParser, 52 GroupExpandedInfo groupExpandedInfo) { 53 mTermsDocuments = checkNotNull(termsDocuments); 54 mInflater = checkNotNull(layoutInflater); 55 mHtmlToSpannedParser = checkNotNull(htmlToSpannedParser); 56 mGroupExpandedInfo = checkNotNull(groupExpandedInfo); 57 mContextMenuMaker = checkNotNull(contextMenuMaker); 58 } 59 60 @Override 61 public int getGroupCount() { 62 return mTermsDocuments.size(); 63 } 64 65 @Override 66 public int getChildrenCount(int groupPosition) { 67 return 1; // one content piece per header 68 } 69 70 @Override 71 public TermsDocument getGroup(int groupPosition) { 72 return getDisclaimer(groupPosition); 73 } 74 75 @Override 76 public TermsDocument getChild(int groupPosition, int childPosition) { 77 return getDisclaimer(groupPosition); 78 } 79 80 @Override 81 public long getGroupId(int groupPosition) { 82 return groupPosition; 83 } 84 85 @Override 86 public long getChildId(int groupPosition, int childPosition) { 87 return childPosition; 88 } 89 90 @Override 91 public boolean hasStableIds() { 92 return true; 93 } 94 95 // TODO: encapsulate this logic - too much direct view manipulation 96 @Override 97 public View getGroupView(int groupPosition, boolean isExpanded, View convertView, 98 ViewGroup parent) { 99 String heading = getDisclaimer(groupPosition).getHeading(); 100 101 View groupView = convertView != null ? convertView : mInflater.inflate( 102 R.layout.terms_disclaimer_header, parent, false); 103 groupView.setContentDescription( 104 parent.getResources().getString(R.string.section_heading, heading)); 105 groupView.setAccessibilityDelegate(new View.AccessibilityDelegate() { 106 @Override public void onInitializeAccessibilityNodeInfo(View host, 107 AccessibilityNodeInfo info) { 108 super.onInitializeAccessibilityNodeInfo(host, info); 109 info.addAction(new AccessibilityNodeInfo.AccessibilityAction( 110 AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.getId(), 111 parent.getResources().getString( 112 isExpanded ? R.string.collapse : R.string.expand))); 113 } 114 }); 115 116 TextView textView = groupView.findViewById(R.id.header_text); 117 textView.setText(heading); 118 119 ImageView chevron = groupView.findViewById(R.id.chevron); 120 chevron.setRotation(isExpanded ? 90 : -90); // chevron down / up retrospectively 121 groupView.findViewById(R.id.divider).setVisibility( 122 shouldShowGroupDivider(groupPosition) ? View.VISIBLE : View.INVISIBLE); 123 124 return groupView; 125 } 126 127 /** 128 * Helps avoid a double thick divider line: one above header, one from the bottom of prev child 129 */ 130 private boolean shouldShowGroupDivider(int groupPosition) { 131 return mGroupExpandedInfo.isGroupExpanded(groupPosition) 132 && (groupPosition == 0 || !mGroupExpandedInfo.isGroupExpanded(groupPosition - 1)); 133 } 134 135 // TODO: encapsulate this logic - too much direct view manipulation 136 @Override 137 public View getChildView(int groupPosition, int childPosition, boolean isLastChild, 138 View convertView, ViewGroup parent) { 139 View view = convertView != null ? convertView : mInflater.inflate( 140 R.layout.terms_disclaimer_content, parent, false); 141 142 TermsDocument disclaimer = getDisclaimer(groupPosition); 143 TextView textView = view.findViewById(R.id.disclaimer_content); 144 Spanned content = mHtmlToSpannedParser.parseHtml(disclaimer.getContent()); 145 textView.setText(content); 146 textView.setContentDescription( 147 parent.getResources().getString(R.string.section_content, disclaimer.getHeading(), 148 content)); 149 textView.setMovementMethod(LinkMovementMethod.getInstance()); // makes html links clickable 150 mContextMenuMaker.registerWithActivity(textView); 151 return view; 152 } 153 154 private TermsDocument getDisclaimer(int index) { 155 return mTermsDocuments.get(index); 156 } 157 158 @Override 159 public boolean isChildSelectable(int groupPosition, int childPosition) { 160 return false; 161 } 162 163 interface GroupExpandedInfo { 164 boolean isGroupExpanded(int groupPosition); 165 } 166 }