You've already forked android_translation_layer
mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-10-27 11:48:10 -07:00
ListView: implement header and footer Views
Underlying HeaderViewListAdapter class is copied from AOSP
This commit is contained in:
@@ -8,7 +8,7 @@ import android.view.ViewGroup;
|
|||||||
public abstract class AbsListView extends AdapterView {
|
public abstract class AbsListView extends AdapterView {
|
||||||
|
|
||||||
public boolean mIsChildViewEnabled = false; // this field gets directly accessed by androidx DropDownListView
|
public boolean mIsChildViewEnabled = false; // this field gets directly accessed by androidx DropDownListView
|
||||||
private Observer observer = new Observer();
|
protected Observer observer = new Observer();
|
||||||
|
|
||||||
public AbsListView(Context context) {
|
public AbsListView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -79,7 +79,7 @@ public abstract class AbsListView extends AdapterView {
|
|||||||
|
|
||||||
public interface SelectionBoundsAdjuster {}
|
public interface SelectionBoundsAdjuster {}
|
||||||
|
|
||||||
private class Observer extends DataSetObserver {
|
class Observer extends DataSetObserver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChanged() {
|
public void onChanged() {
|
||||||
|
|||||||
@@ -1,5 +1,231 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2006 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
package android.widget;
|
package android.widget;
|
||||||
|
|
||||||
public class HeaderViewListAdapter {
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import android.database.DataSetObserver;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ListAdapter used when a ListView has header views. This ListAdapter
|
||||||
|
* wraps another one and also keeps track of the header views and their
|
||||||
|
* associated data objects.
|
||||||
|
*<p>This is intended as a base class; you will probably not need to
|
||||||
|
* use this class directly in your own code.
|
||||||
|
*/
|
||||||
|
public class HeaderViewListAdapter implements ListAdapter, Filterable {
|
||||||
|
|
||||||
|
private final ListAdapter mAdapter;
|
||||||
|
|
||||||
|
// These two ArrayList are assumed to NOT be null.
|
||||||
|
// They are indeed created when declared in ListView and then shared.
|
||||||
|
ArrayList<ListView.FixedViewInfo> mHeaderViewInfos;
|
||||||
|
ArrayList<ListView.FixedViewInfo> mFooterViewInfos;
|
||||||
|
|
||||||
|
// Used as a placeholder in case the provided info views are indeed null.
|
||||||
|
// Currently only used by some CTS tests, which may be removed.
|
||||||
|
static final ArrayList<ListView.FixedViewInfo> EMPTY_INFO_LIST =
|
||||||
|
new ArrayList<ListView.FixedViewInfo>();
|
||||||
|
|
||||||
|
boolean mAreAllFixedViewsSelectable;
|
||||||
|
|
||||||
|
public HeaderViewListAdapter(ArrayList<ListView.FixedViewInfo> headerViewInfos,
|
||||||
|
ArrayList<ListView.FixedViewInfo> footerViewInfos,
|
||||||
|
ListAdapter adapter) {
|
||||||
|
mAdapter = adapter;
|
||||||
|
|
||||||
|
if (headerViewInfos == null) {
|
||||||
|
mHeaderViewInfos = EMPTY_INFO_LIST;
|
||||||
|
} else {
|
||||||
|
mHeaderViewInfos = headerViewInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (footerViewInfos == null) {
|
||||||
|
mFooterViewInfos = EMPTY_INFO_LIST;
|
||||||
|
} else {
|
||||||
|
mFooterViewInfos = footerViewInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
mAreAllFixedViewsSelectable =
|
||||||
|
areAllListInfosSelectable(mHeaderViewInfos)
|
||||||
|
&& areAllListInfosSelectable(mFooterViewInfos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeadersCount() {
|
||||||
|
return mHeaderViewInfos.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFootersCount() {
|
||||||
|
return mFooterViewInfos.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return mAdapter == null || mAdapter.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean areAllListInfosSelectable(ArrayList<ListView.FixedViewInfo> infos) {
|
||||||
|
if (infos != null) {
|
||||||
|
for (ListView.FixedViewInfo info : infos) {
|
||||||
|
if (!info.isSelectable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeHeader(View v) {
|
||||||
|
for (int i = 0; i < mHeaderViewInfos.size(); i++) {
|
||||||
|
ListView.FixedViewInfo info = mHeaderViewInfos.get(i);
|
||||||
|
if (info.view == v) {
|
||||||
|
mHeaderViewInfos.remove(i);
|
||||||
|
|
||||||
|
mAreAllFixedViewsSelectable =
|
||||||
|
areAllListInfosSelectable(mHeaderViewInfos)
|
||||||
|
&& areAllListInfosSelectable(mFooterViewInfos);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeFooter(View v) {
|
||||||
|
for (int i = 0; i < mFooterViewInfos.size(); i++) {
|
||||||
|
ListView.FixedViewInfo info = mFooterViewInfos.get(i);
|
||||||
|
if (info.view == v) {
|
||||||
|
mFooterViewInfos.remove(i);
|
||||||
|
|
||||||
|
mAreAllFixedViewsSelectable =
|
||||||
|
areAllListInfosSelectable(mHeaderViewInfos)
|
||||||
|
&& areAllListInfosSelectable(mFooterViewInfos);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
if (mAdapter != null) {
|
||||||
|
return getFootersCount() + getHeadersCount() + mAdapter.getCount();
|
||||||
|
} else {
|
||||||
|
return getFootersCount() + getHeadersCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getItem(int position) {
|
||||||
|
// Header (negative positions will throw an IndexOutOfBoundsException)
|
||||||
|
int numHeaders = getHeadersCount();
|
||||||
|
if (position < numHeaders) {
|
||||||
|
return mHeaderViewInfos.get(position).data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapter
|
||||||
|
final int adjPosition = position - numHeaders;
|
||||||
|
int adapterCount = 0;
|
||||||
|
if (mAdapter != null) {
|
||||||
|
adapterCount = mAdapter.getCount();
|
||||||
|
if (adjPosition < adapterCount) {
|
||||||
|
return mAdapter.getItem(adjPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer (off-limits positions will throw an IndexOutOfBoundsException)
|
||||||
|
return mFooterViewInfos.get(adjPosition - adapterCount).data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getItemId(int position) {
|
||||||
|
int numHeaders = getHeadersCount();
|
||||||
|
if (mAdapter != null && position >= numHeaders) {
|
||||||
|
int adjPosition = position - numHeaders;
|
||||||
|
int adapterCount = mAdapter.getCount();
|
||||||
|
if (adjPosition < adapterCount) {
|
||||||
|
return mAdapter.getItemId(adjPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasStableIds() {
|
||||||
|
if (mAdapter != null) {
|
||||||
|
return mAdapter.hasStableIds();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
// Header (negative positions will throw an IndexOutOfBoundsException)
|
||||||
|
int numHeaders = getHeadersCount();
|
||||||
|
if (position < numHeaders) {
|
||||||
|
return mHeaderViewInfos.get(position).view;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapter
|
||||||
|
final int adjPosition = position - numHeaders;
|
||||||
|
int adapterCount = 0;
|
||||||
|
if (mAdapter != null) {
|
||||||
|
adapterCount = mAdapter.getCount();
|
||||||
|
if (adjPosition < adapterCount) {
|
||||||
|
return mAdapter.getView(adjPosition, convertView, parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer (off-limits positions will throw an IndexOutOfBoundsException)
|
||||||
|
return mFooterViewInfos.get(adjPosition - adapterCount).view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
int numHeaders = getHeadersCount();
|
||||||
|
if (mAdapter != null && position >= numHeaders) {
|
||||||
|
int adjPosition = position - numHeaders;
|
||||||
|
int adapterCount = mAdapter.getCount();
|
||||||
|
if (adjPosition < adapterCount) {
|
||||||
|
return mAdapter.getItemViewType(adjPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return /*ITEM_VIEW_TYPE_HEADER_OR_FOOTER*/ -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getViewTypeCount() {
|
||||||
|
if (mAdapter != null) {
|
||||||
|
return mAdapter.getViewTypeCount();
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerDataSetObserver(DataSetObserver observer) {
|
||||||
|
if (mAdapter != null) {
|
||||||
|
mAdapter.registerDataSetObserver(observer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregisterDataSetObserver(DataSetObserver observer) {
|
||||||
|
if (mAdapter != null) {
|
||||||
|
mAdapter.unregisterDataSetObserver(observer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListAdapter getWrappedAdapter() {
|
||||||
|
return mAdapter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package android.widget;
|
package android.widget;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@@ -7,6 +8,21 @@ import android.view.View;
|
|||||||
|
|
||||||
public class ListView extends AbsListView {
|
public class ListView extends AbsListView {
|
||||||
|
|
||||||
|
static class FixedViewInfo {
|
||||||
|
public View view;
|
||||||
|
public Object data;
|
||||||
|
public boolean isSelectable;
|
||||||
|
|
||||||
|
public FixedViewInfo(View view, Object data, boolean isSelectable) {
|
||||||
|
this.view = view;
|
||||||
|
this.data = data;
|
||||||
|
this.isSelectable = isSelectable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<FixedViewInfo> headerViews = new ArrayList<FixedViewInfo>();
|
||||||
|
private ArrayList<FixedViewInfo> footerViews = new ArrayList<FixedViewInfo>();
|
||||||
|
|
||||||
public ListView(Context context) {
|
public ListView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
@@ -15,35 +31,72 @@ public class ListView extends AbsListView {
|
|||||||
super(context, attributeSet);
|
super(context, attributeSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ListView(Context context, AttributeSet attributeSet, int defStyleAttr) {
|
||||||
|
super(context, attributeSet, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAdapter(ListAdapter adapter) {
|
||||||
|
if (getHeaderViewsCount() > 0 || getFooterViewsCount() > 0) {
|
||||||
|
adapter = new HeaderViewListAdapter(headerViews, footerViews, adapter);
|
||||||
|
}
|
||||||
|
super.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
public int getDividerHeight() {return 0;}
|
public int getDividerHeight() {return 0;}
|
||||||
|
|
||||||
public Drawable getDivider() {return null;}
|
public Drawable getDivider() {return null;}
|
||||||
|
|
||||||
public void setTextFilterEnabled(boolean enabled) {}
|
public void setTextFilterEnabled(boolean enabled) {}
|
||||||
|
|
||||||
public void addHeaderView(View v, Object data, boolean isSelectable) {}
|
public void addHeaderView(View v, Object data, boolean isSelectable) {
|
||||||
|
headerViews.add(new FixedViewInfo(v, data, isSelectable));
|
||||||
|
if (getAdapter() instanceof HeaderViewListAdapter) {
|
||||||
|
observer.onChanged();
|
||||||
|
} else if (getAdapter() != null) {
|
||||||
|
setAdapter(getAdapter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setDrawSelectorOnTop(boolean dummy) {}
|
public void setDrawSelectorOnTop(boolean dummy) {}
|
||||||
|
|
||||||
public void addHeaderView(View view) {}
|
public void addHeaderView(View view) {
|
||||||
|
addHeaderView(view, null, true);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean removeHeaderView(View view) { return true; }
|
public boolean removeHeaderView(View view) {
|
||||||
|
boolean result = false;
|
||||||
|
if (getAdapter() instanceof HeaderViewListAdapter)
|
||||||
|
result = ((HeaderViewListAdapter)getAdapter()).removeHeader(view);
|
||||||
|
if (result)
|
||||||
|
observer.onChanged();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public int getHeaderViewsCount() {
|
public int getHeaderViewsCount() {
|
||||||
return 0;
|
return headerViews.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFooterViewsCount() {
|
public int getFooterViewsCount() {
|
||||||
return 0;
|
return footerViews.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDivider(Drawable drawable) {}
|
public void setDivider(Drawable drawable) {}
|
||||||
|
|
||||||
public void setSelectionFromTop(int position, int y) {}
|
public void setSelectionFromTop(int position, int y) {}
|
||||||
|
|
||||||
public void addFooterView(View v, Object data, boolean isSelectable) {}
|
public void addFooterView(View v, Object data, boolean isSelectable) {
|
||||||
|
footerViews.add(new FixedViewInfo(v, data, isSelectable));
|
||||||
|
if (getAdapter() instanceof HeaderViewListAdapter) {
|
||||||
|
observer.onChanged();
|
||||||
|
} else if (getAdapter() != null) {
|
||||||
|
setAdapter(getAdapter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void addFooterView(View v) {}
|
public void addFooterView(View v) {
|
||||||
|
addFooterView(v, null, true);
|
||||||
|
}
|
||||||
|
|
||||||
public void setDividerHeight(int height) {}
|
public void setDividerHeight(int height) {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user