Voici l'implémentation de la classe SimpleListView
. Je sais que c'est inefficace et je suis sûr qu'il contient des erreurs, mais il montre comment mesurer une largeur d'une vue de liste.
Je recommande également de lire this article.
public class SimpleListView extends AdapterView<ListAdapter> {
private ListAdapter adapter;
private Drawable divider;
private int dividerHeight;
private boolean clipDivider;
public SimpleListView(final Context context)
{
this(context, null);
}
public SimpleListView(final Context context, final AttributeSet attrs)
{
this(context, attrs, android.R.attr.listViewStyle);
}
public SimpleListView(final Context context, final AttributeSet attrs, final int defStyle)
{
super(context, attrs, defStyle);
final TypedArray array =
context.obtainStyledAttributes(attrs, R.styleable.SimpleListView, defStyle, 0);
final Drawable dividerAttribute =
array.getDrawable(R.styleable.SimpleListView_android_divider);
if(dividerAttribute != null) {
setDivider(dividerAttribute);
}
final int dividerHeightAttribute =
array.getDimensionPixelSize(R.styleable.SimpleListView_android_dividerHeight, 0);
if(dividerHeightAttribute != 0) {
setDividerHeight(dividerHeightAttribute);
}
array.recycle();
}
public Drawable getDivider()
{
return this.divider;
}
public void setDivider(final Drawable newDivider)
{
if(newDivider != null) {
this.dividerHeight = newDivider.getIntrinsicHeight();
this.clipDivider = newDivider instanceof ColorDrawable;
} else {
this.dividerHeight = 0;
this.clipDivider = false;
}
this.divider = newDivider;
requestLayout();
}
public int getDividerHeight()
{
return this.dividerHeight;
}
public void setDividerHeight(final int newHeight)
{
this.dividerHeight = newHeight;
requestLayout();
}
@Override
public ListAdapter getAdapter()
{
return this.adapter;
}
@Override
public void setAdapter(final ListAdapter adapter)
{
this.adapter = adapter;
removeAllViewsInLayout();
requestLayout();
}
@Override
public View getSelectedView()
{
throw new UnsupportedOperationException(
"SimpleListView.getSelectedView() is not supported");
}
@Override
public void setSelection(final int position)
{
throw new UnsupportedOperationException(
"SimpleListView.setSelection(int) is not supported");
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int innerWidth = 0;
int innerHeight = 0;
final int itemCount = this.adapter == null ? 0 : this.adapter.getCount();
if(itemCount > 0
&& (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY)) {
for(int i = 0; i < itemCount; ++i) {
final View convertView = getChildAt(i);
final View child = this.adapter.getView(i, convertView, this);
if(convertView == null) {
LayoutParams params = child.getLayoutParams();
if(params == null) {
params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
child.setLayoutParams(params);
}
addViewInLayout(child, i, params);
}
if(child.getLayoutParams() instanceof MarginLayoutParams) {
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
} else {
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
innerWidth = Math.max(innerWidth, child.getMeasuredWidth());
innerHeight += child.getMeasuredHeight();
}
innerHeight += (itemCount - 1) * this.dividerHeight;
}
if(widthMode != MeasureSpec.EXACTLY) {
final int newWidthSize = getPaddingLeft() + getPaddingRight() + innerWidth;
widthSize =
widthMode == MeasureSpec.AT_MOST ? Math.min(widthSize, newWidthSize)
: newWidthSize;
}
if(heightMode != MeasureSpec.EXACTLY) {
final int newHeightSize = getPaddingTop() + getPaddingBottom() + innerHeight;
heightSize =
heightMode == MeasureSpec.AT_MOST ? Math.min(heightSize, newHeightSize)
: newHeightSize;
}
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onLayout(final boolean changed, final int left, final int top, final int right,
final int bottom)
{
super.onLayout(changed, left, top, right, bottom);
if(this.adapter == null) {
return;
}
positionItems();
invalidate();
}
private void positionItems()
{
int top = getPaddingTop();
final int left = getPaddingLeft();
for(int i = 0, count = getChildCount(); i < count; ++i) {
final View child = getChildAt(i);
final int width = child.getMeasuredWidth();
final int height = child.getMeasuredHeight();
child.layout(left, top, left + width, top + height);
top += height + this.dividerHeight;
}
}
@Override
protected void dispatchDraw(final Canvas canvas)
{
final boolean drawDividers = this.dividerHeight > 0 && this.divider != null;
if(drawDividers) {
final int left = getPaddingLeft();
final int right = getWidth() - getPaddingRight();
final Rect dividerBounds = new Rect(left, 0, right, 0);
for(int i = 0, count = getChildCount(); i < count - 1; ++i) {
final View child = getChildAt(i);
dividerBounds.top = dividerBounds.bottom + child.getMeasuredHeight();
dividerBounds.bottom = dividerBounds.top + this.dividerHeight;
drawDivider(canvas, dividerBounds);
}
}
super.dispatchDraw(canvas);
}
private void drawDivider(final Canvas canvas, final Rect bounds)
{
if(!this.clipDivider) {
this.divider.setBounds(bounds);
} else {
canvas.save();
canvas.clipRect(bounds);
}
this.divider.draw(canvas);
if(this.clipDivider) {
canvas.restore();
}
}
}
Merci pour le partage! – shiami
J'ai écrit une classe 'SimpleListView' qui étend la classe' AdapterView'. Il a de très mauvaises performances mais il peut changer sa largeur en fonction des largeurs de ses enfants. Et je peux partager le code source si vous le souhaitez. – Michael
Pixie, pouvez-vous partager votre réponse – pengwang