如何模仿Lollipop的联系人应用程序中的listView stickey项目?

and*_*per 17 android listview android-5.0-lollipop pagertitlestrip roundedbitmapdrawable

背景

谷歌最近发布了一个新版本的Android,它有一个如下所示的联系人应用程序:

在此输入图像描述

问题

我需要模仿这种列表,但我不知道如何做得好.

这包括3个主要组成部分:

  1. stickey标题,只要顶级联系人的名字以此字母开头,就会保留.

  2. 圆形照片或圆圈+字母(适用于没有照片的联系人)

  3. PagerTitleStrip,在项目之间具有统一的间距,并尝试在屏幕上显示所有内容(或允许在需要时滚动).

我发现了什么

  1. 有很多第三方库,但它们处理stickey-headers,它们是listView本身项目的一部分.他们没有左边的标题,但是在项目的顶部.

    这里,左侧以与右侧不同的方式移动.它可以粘住,如果不需要粘贴(例如,因为该部分有一个项目),它会滚动.

  2. 我注意到对于圆形照片,我可以使用名为" RoundedBitmapDrawableFactory " 的新(?)类(它创建" RoundedBitmapDrawable ").这可能会让我很好地将照片变成圆形.但是,它不适用于字母(用于没有照片的联系人),但我想我可以将textView放在上面,并将背景设置为一种颜色.

    另外,我注意到为了使用"RoundedBitmapDrawable"(使其成为真正的圆形),我必须为它提供一个方形大小的位图.否则,它会有一个奇怪的形状.

  3. 我尝试使用" setTextSpacing "来最小化项目之间的空间,但它似乎不起作用.我也找不到任何方式来设置/自定义PagerTitleStrip就像在联系人应用程序上一样.

    我也试过使用" PagerTabStrip ",但它也没有帮助.

这个问题

您如何模仿Google实施此屏幕的方式?

进一步来说:

  1. 如何使左侧的行为与联系人应用程序类似?

  2. 这是实施圆形照片的最佳方式吗?在使用特殊drawable之前,我真的必须将位图裁剪成正方形吗?是否有使用哪种颜色的设计指南?是否有更正式的方式来使用圆形文本单元格?

  3. 你如何设置PagerTitleStrip的样式,使其具有与联系人应用程序相同的外观和感觉?


Github项目

编辑:对#1和#2,我做了Github上的一个项目,在这里.可悲的是,我也发现了一个重要的错误,所以我也在这里发布了它.

and*_*per 6

好的,我已经设法解决了我写的所有问题:

1.我改变了第三方库的工作方式(我不记得我从哪里得到了库,但是这个非常相似),通过改变每一行的布局,使得标题在左边内容本身.这只是一个布局XML文件的问题,你已经完成了很多工作.也许我会为这两种解决方案发布一个很好的库.

这是我的观点.这不是官方的实施(没有找到),所以我自己做了些什么.它可以更有效,但至少它很容易理解,而且非常灵活:

public class CircularView extends ViewSwitcher {
    private ImageView mImageView;
    private TextView mTextView;
    private Bitmap mBitmap;
    private CharSequence mText;
    private int mBackgroundColor = 0;
    private int mImageResId = 0;

    public CircularView(final Context context) {
        this(context, null);
    }

    public CircularView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        addView(mImageView = new ImageView(context), new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT, Gravity.CENTER));
        addView(mTextView = new TextView(context), new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT, Gravity.CENTER));
        mTextView.setGravity(Gravity.CENTER);
        if (isInEditMode())
            setTextAndBackgroundColor("", 0xFFff0000);
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        final int measuredWidth = getMeasuredWidth();
        final int measuredHeight = getMeasuredHeight();
        if (measuredWidth != 0 && measuredHeight != 0)
            drawContent(measuredWidth, measuredHeight);
    }

    @SuppressWarnings("deprecation")
    private void drawContent(final int measuredWidth, final int measuredHeight) {
        ShapeDrawable roundedBackgroundDrawable = null;
        if (mBackgroundColor != 0) {
            roundedBackgroundDrawable = new ShapeDrawable(new OvalShape());
            roundedBackgroundDrawable.getPaint().setColor(mBackgroundColor);
            roundedBackgroundDrawable.setIntrinsicHeight(measuredHeight);
            roundedBackgroundDrawable.setIntrinsicWidth(measuredWidth);
            roundedBackgroundDrawable.setBounds(new Rect(0, 0, measuredWidth, measuredHeight));
        }
        if (mImageResId != 0) {
            mImageView.setBackgroundDrawable(roundedBackgroundDrawable);
            mImageView.setImageResource(mImageResId);
            mImageView.setScaleType(ScaleType.CENTER_INSIDE);
        } else if (mText != null) {
            mTextView.setText(mText);
            mTextView.setBackgroundDrawable(roundedBackgroundDrawable);
            // mTextView.setPadding(0, measuredHeight / 4, 0, measuredHeight / 4);
            mTextView.setTextSize(measuredHeight / 5);
        } else if (mBitmap != null) {
            mImageView.setScaleType(ScaleType.FIT_CENTER);
            mImageView.setBackgroundDrawable(roundedBackgroundDrawable);
            mBitmap = ThumbnailUtils.extractThumbnail(mBitmap, measuredWidth, measuredHeight);
            final RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(),
                    mBitmap);
            roundedBitmapDrawable.setCornerRadius((measuredHeight + measuredWidth) / 4);
            mImageView.setImageDrawable(roundedBitmapDrawable);
        }
        resetValuesState(false);
    }

    public void setTextAndBackgroundColor(final CharSequence text, final int backgroundColor) {
        resetValuesState(true);
        while (getCurrentView() != mTextView)
            showNext();
        this.mBackgroundColor = backgroundColor;
        mText = text;
        final int height = getHeight(), width = getWidth();
        if (height != 0 && width != 0)
            drawContent(width, height);
    }

    public void setImageResource(final int imageResId, final int backgroundColor) {
        resetValuesState(true);
        while (getCurrentView() != mImageView)
            showNext();
        mImageResId = imageResId;
        this.mBackgroundColor = backgroundColor;
        final int height = getHeight(), width = getWidth();
        if (height != 0 && width != 0)
            drawContent(width, height);
    }

    public void setImageBitmap(final Bitmap bitmap) {
        setImageBitmapAndBackgroundColor(bitmap, 0);
    }

    public void setImageBitmapAndBackgroundColor(final Bitmap bitmap, final int backgroundColor) {
        resetValuesState(true);
        while (getCurrentView() != mImageView)
            showNext();
        this.mBackgroundColor = backgroundColor;
        mBitmap = bitmap;
        final int height = getHeight(), width = getWidth();
        if (height != 0 && width != 0)
            drawContent(width, height);
    }

    private void resetValuesState(final boolean alsoResetViews) {
        mBackgroundColor = mImageResId = 0;
        mBitmap = null;
        mText = null;
        if (alsoResetViews) {
            mTextView.setText(null);
            mTextView.setBackgroundDrawable(null);
            mImageView.setImageBitmap(null);
            mImageView.setBackgroundDrawable(null);
        }
    }

    public ImageView getImageView() {
        return mImageView;
    }

    public TextView getTextView() {
        return mTextView;
    }

}
Run Code Online (Sandbox Code Playgroud)

我发现了一个很好的库,叫做PagerSlidingTabStrip.但是,没有找到一种正式的方式来塑造本土的风格.

另一种方法是查看Google的样本,该样本在Android-Studio中可用,并称为"SlidingTabLayout".它显示了它是如何完成的.

编辑:对#3更好地库是在这里,所谓的"PagerSlidingTabStrip"了.