如何模仿 Lollipop 的通讯录应用程序中的 listView 粘性项目? [英] How to mimic the listView stickey-items like on Lollipop's contacts app?

查看:17
本文介绍了如何模仿 Lollipop 的通讯录应用程序中的 listView 粘性项目?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Google has recently published a new version of Android, which has a contact app that look like this :

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

I need to mimic this kind of list, but I can't find out how to do it well.

这包括 3 个主要组件:

This consists of 3 main components:

  1. 粘性标题,只要顶级联系人的姓名以该字母开头就一直存在.

  1. the stickey titles, which stay as long as the top contact has the name that starts with this letter.

圆形照片或圆形+字母(对于没有照片的联系人)

The circular photos or circle+letter (for contacts that don't have photos)

PagerTitleStrip,它在项目之间具有统一的间距,并尝试将它们全部显示在屏幕上(或允许在需要时滚动).

the PagerTitleStrip, which has uniform spacing between the items, and tries to show them all on the screen (or allow to scroll if needed).

我发现了什么

  1. 有很多第三方库,但它们处理粘性标头,这是 listView 本身的项目的一部分.它们的标题不在左侧,而是在项目的顶部.

  1. There are plenty of third party libraries, but that handle stickey-headers, which are a part of the items of the listView itself. They don't have the title on the left, but on the top of the items.

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

Here, the left side moves in a different way than the right side. It can stick, and if there is no need to stick (because the section has one item, for example) it scrolls.

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

I've noticed that for the circular photos, I can use the new (?) class called "RoundedBitmapDrawableFactory" (which creates "RoundedBitmapDrawable" ). This will probably allow me to put a photo into a circular shape nicely. However, it won't work for letters (used for contacts that don't have a photo), but I think I can put a textView on top, and set the background to a color.

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

Also, I've noticed that in order to use the "RoundedBitmapDrawable" well (to make it truly circular), I must provide it with a square sized bitmap. Otherwise, it will have a weird shape.

我试过使用 "setTextSpacing"尽量减少项目之间的空间,但它似乎不起作用.我也找不到任何方法来设置/自定义 PagerTitleStrip 的样式,使其与联系人应用程序上的一样.

I've tried using "setTextSpacing" to minimize the space between the items, but it doesn't seem to work. I also couldn't find any way to style/customize the PagerTitleStrip to be like on the contacts app.

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

I've also tried using "PagerTabStrip" , but it also didn't help.

问题

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

The question

How can you mimic the way that Google has implemented this screen?

更具体地说:

  1. 如何让左侧的行为与联系人应用中的一样?

  1. How can I make the left side behave like on the contacts app?

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

Is this the best way to implement the circular photo? Do I really have to crop the bitmap into a square before using the special drawable ? Are there any design guidelines for which colors to use? Is there a more official way to use the circle-text cell?

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

How do you style the PagerTitleStrip to have the same look&feel as on the contacts app?


Github 项目

对于 #1 和 #2,我在 Github 上做了一个项目,这里.遗憾的是,我还发现了一个重要的错误,因此我还发布了关于它的此处.

推荐答案

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

ok, I've managed to solve all of the issues I've written about:

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

1.I changed the way that the third party library works (I don't remember where I got the library from, but this one is very similar) , by changing the layout of each row, so that the header would be on the left of the content itself. It's just a matter of a layout XML file and you're pretty much done. Maybe I will publish a nice library for both of those solutions.

2.这是我制作的视图.这不是官方实现(没有找到),所以我自己做了一些.它可以更高效,但至少它很容易理解,也很灵活:

2.This is the view I've made. It's not an official implementation (didn't find any), so I made something by myself. It can be more efficient, but at least it's quite easy to understand and also quite flexible:

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;
    }

}

3.我找到了一个很好的库,叫做 PagerSlidingTabStrip.不过,没有找到一种官方方式来设计原生样式.

3.I've found a nice library that does it, called PagerSlidingTabStrip . Didn't find an official way to style the native one, though.

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

Another way is to look at Google's sample which is available right within Android-Studio, and is called "SlidingTabLayout". It shows how it's done.

#3 更好的库是此处,也称为PagerSlidingTabStrip".

a better library for #3 is here, called "PagerSlidingTabStrip" too.

这篇关于如何模仿 Lollipop 的通讯录应用程序中的 listView 粘性项目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆