1 /* 2 * Copyright (C) 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 17 package com.android.documentsui.sidebar; 18 19 import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; 20 21 import android.app.Activity; 22 import android.os.Looper; 23 import android.view.View; 24 import android.view.View.OnDragListener; 25 import android.view.ViewGroup; 26 import android.widget.ArrayAdapter; 27 import android.widget.ListView; 28 29 import com.android.documentsui.R; 30 31 import java.util.HashMap; 32 import java.util.List; 33 import java.util.Map; 34 35 /** 36 * The adapter for the {@link android.widget.ListView} in sidebar. It contains the list of 37 * {@link Item}s and provides sub-views to {@link android.widget.ListView}. 38 */ 39 class RootsAdapter extends ArrayAdapter<Item> { 40 private static final int TYPE_ROOT = 0; 41 private static final int TYPE_APP = 1; 42 private static final int TYPE_ROOT_AND_APP = 2; 43 private static final int TYPE_SPACER = 3; 44 45 private static final Map<String, Long> sIdMap = new HashMap<>(); 46 // the next available id to associate with a new string id 47 private static long sNextAvailableId; 48 49 private final OnDragListener mDragListener; 50 RootsAdapter( Activity activity, List<Item> items, OnDragListener dragListener)51 public RootsAdapter( 52 Activity activity, 53 List<Item> items, 54 OnDragListener dragListener) { 55 super(activity, 0, items); 56 57 mDragListener = dragListener; 58 } 59 60 @Override hasStableIds()61 public boolean hasStableIds() { 62 return true; 63 } 64 65 @Override getItemId(int position)66 public long getItemId(int position) { 67 // Ensure this method is only called in main thread because we don't have any 68 // concurrency protection. 69 assert(Looper.myLooper() == Looper.getMainLooper()); 70 71 String stringId = getItem(position).stringId; 72 73 long id; 74 if (sIdMap.containsKey(stringId)) { 75 id = sIdMap.get(stringId); 76 } else { 77 id = sNextAvailableId++; 78 sIdMap.put(stringId, id); 79 } 80 81 return id; 82 } 83 84 @Override getView(int position, View convertView, ViewGroup parent)85 public View getView(int position, View convertView, ViewGroup parent) { 86 final Item item = getItem(position); 87 final View view = item.getView(convertView, parent); 88 89 if (isUseMaterial3FlagEnabled()) { 90 // In order to have hover showing on the list item, we need to have 91 // "android:clickable=true" on the list item level, which will break the click handler 92 // because it's set at the list level, so here we "bubble up" the item level click 93 // event to the list level by explicitly calling the "performItemClick" on the list 94 // level. 95 view.setOnClickListener( 96 v -> ((ListView) parent).performItemClick(v, position, getItemId(position))); 97 } 98 99 if (item.isRoot()) { 100 view.setTag(R.id.item_position_tag, position); 101 view.setOnDragListener(mDragListener); 102 } else { 103 view.setTag(R.id.item_position_tag, null); 104 view.setOnDragListener(null); 105 } 106 return view; 107 } 108 109 @Override areAllItemsEnabled()110 public boolean areAllItemsEnabled() { 111 return false; 112 } 113 114 @Override isEnabled(int position)115 public boolean isEnabled(int position) { 116 return getItemViewType(position) != TYPE_SPACER; 117 } 118 119 @Override getItemViewType(int position)120 public int getItemViewType(int position) { 121 final Item item = getItem(position); 122 if (item instanceof RootAndAppItem) { 123 return TYPE_ROOT_AND_APP; 124 } else if (item instanceof RootItem) { 125 return TYPE_ROOT; 126 } else if (item instanceof AppItem) { 127 return TYPE_APP; 128 } else { 129 return TYPE_SPACER; 130 } 131 } 132 133 @Override getViewTypeCount()134 public int getViewTypeCount() { 135 return 4; 136 } 137 } 138