如何模仿的ListView stickey项像棒棒糖的联系人应用程序? [英] How to mimic the listView stickey-items like on Lollipop's contacts app?

查看:210
本文介绍了如何模仿的ListView stickey项像棒棒糖的联系人应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

谷歌最近发布了新版本的Andr​​oid,它有一个联系人应用程序,它是这样的:

问题

我要模仿这样的名单,但我不能找出如何把它做好。

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

  1. 在stickey冠军,只要上面有接触与此字母开头的名称而留下来。

  2. 圆形照片或圆形+字母(联系人没有照片)

  3. 的PagerTitleStrip,其具有项之间均匀间隔,并试图显示他们所有的屏幕上(或允许如果需要的话,滚动)。

我发现什么

  1. 有大量的第三方库,但手柄stickey报头,这些都是在ListView本身的项目的一部分。它们不具有在左边的标题,但在这两个项目的顶部。

    下面,以不同的方式比右侧的左侧移动。它可以粘,并且,如果没有必要坚持(因为部分具有一个项,例如)它滚动。

  2. 我已经注意到,在圆形的照片,我可以使用新的(?)类叫做<一href="https://developer.android.com/reference/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.html">RoundedBitmapDrawableFactory" (这将创建<一个href="https://developer.android.com/reference/android/support/v4/graphics/drawable/RoundedBitmapDrawable.html">RoundedBitmapDrawable" )。这可能让我把照片变成圆形很好。但是,它不会为字母(用于没有照片联系人)工作,但我想我可以把上面一个TextView,并设置背景颜色。

    另外,我注意到,为了使用RoundedBitmapDrawable井(使之真正圆形的),我必须给它提供一个平方大小的位图。否则,将有一个奇怪的形状。

  3. 我已经尝试过使用<一href="http://developer.android.com/reference/android/support/v4/view/PagerTitleStrip.html#setTextSpacing(int)">setTextSpacing"最大限度地减少项目之间的空间,但它似乎并没有工作。我也找不到任何办法款式/自定义PagerTitleStrip要像上的联系人应用程序。

    我也试着使用<一href="http://developer.android.com/reference/android/support/v4/view/PagerTabStrip.html">PagerTabStrip" ,但它也没有帮助。

问题

你怎么可以模仿,谷歌已经实现了这个屏幕的方式?

更具体地说:

  1. 我怎样才能让左边表现得像上的​​联系人应用程序?

  2. 这是实施循环照片的最佳方式是什么?难道我真的必须使用特殊的绘制之前裁剪位图到一个正方形?是否有任何的设计指导方针哪些颜色使用?有没有用圆圈文本单元更正式的方式?

  3. 你怎么样式化PagerTitleStrip具有相同的外观和放大器;感觉上的联系人应用程序?


Github的项目

编辑:#1和#2,我已经在Github上, 这里 。可悲的是,我还发现了一个重要的错误,所以我也发表一下 此处

解决方案

没关系,我已经成功地解决所有我已经写的问题:

1.我改变了方式,第三方库的工作方式(我不记得在那里我得到了库中,但<一个href="https://github.com/CyanogenMod/android_packages_apps_Superuser/blob/master/src/com/noshufou/android/su/PinnedHeaderListView.java">this一个 是非常相似的),通过改变每行的布局,使得头部将在内容本身的左侧。这是一个布局的XML文件只是一个问题,你是pretty的多少事。也许我会发布一个不错的库这两个解决方案。

2,本就是我所做的观点。这不是一个正式实施(没有发现任何),所以我用我自己做的东西。它可以更有效的,但至少它很容易理解,也比较灵活:

 公共类CircularView扩展ViewSwitcher {
    私人ImageView的mImageView;
    私人TextView的mTextView;
    私人位图mBitmap;
    私人CharSequence的多行文字;
    私人诠释mBackgroundColor = 0;
    私人诠释mImageResId = 0;

    公共CircularView(最终上下文的背景下){
        这(背景下,NULL);
    }

    公共CircularView(最终上下文的背景下,最终的AttributeSet ATTRS){
        超(背景下,ATTRS);
        addView(mImageView =新ImageView的(环境),新FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT,Gravity.CENTER));
        addView(mTextView =新的TextView(上下文),新FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT,Gravity.CENTER));
        mTextView.setGravity(Gravity.CENTER);
        如果(isInEditMode())
            setTextAndBackgroundColor(,0xFFFF0000地址);
    }

    @覆盖
    保护无效onMeasure(最终诠释widthMeasureSpec,最终诠释heightMeasureSpec){
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);
        最终诠释是measuredWidth = getMeasuredWidth();
        最终诠释是measuredHeight = getMeasuredHeight();
        如果(是measuredWidth = 0&放大器;!&安培;!是measuredHeight = 0)
            drawContent(是measuredWidth,measuredHeight可以);
    }

    @燮pressWarnings(德precation)
    私人无效drawContent(最终诠释是measuredWidth,最终诠释是measuredHeight){
        ShapeDrawable roundedBackgroundDrawable = NULL;
        如果(mBackgroundColor!= 0){
            roundedBackgroundDrawable =新ShapeDrawable(新OvalShape());
            。roundedBackgroundDrawable.getPaint()setColor(mBackgroundColor);
            roundedBackgroundDrawable.setIntrinsicHeight(measuredHeight可以);
            roundedBackgroundDrawable.setIntrinsicWidth(measuredWidth可以);
            roundedBackgroundDrawable.setBounds(新的Rect(0,0,是measuredWidth,是measuredHeight));
        }
        如果(mImageResId!= 0){
            mImageView.setBackgroundDrawable(roundedBackgroundDrawable);
            mImageView.setImageResource(mImageResId);
            mImageView.setScaleType(ScaleType.CENTER_INSIDE);
        }否则,如果(MTEXT!= NULL){
            mTextView.setText(MTEXT);
            mTextView.setBackgroundDrawable(roundedBackgroundDrawable);
            // mTextView.setPadding(0,是measuredHeight / 4,0,是measuredHeight / 4);
            mTextView.setTextSize(是measuredHeight / 5);
        }否则,如果(mBitmap!= NULL){
            mImageView.setScaleType(ScaleType.FIT_CENTER);
            mImageView.setBackgroundDrawable(roundedBackgroundDrawable);
            mBitmap = ThumbnailUtils.extractThumbnail(mBitmap,是measuredWidth,measuredHeight可以);
            最后RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources()
                    mBitmap);
            roundedBitmapDrawable.setCornerRadius((是measuredHeight +是measuredWidth)/ 4);
            mImageView.setImageDrawable(roundedBitmapDrawable);
        }
        resetValues​​State(假);
    }

    公共无效setTextAndBackgroundColor(最终CharSequence的文字,最终诠释的backgroundColor){
        resetValues​​State(真正的);
        而(getCurrentView()!= mTextView)
            showNext();
        this.mBackgroundColor =的backgroundColor;
        多行文字=文本;
        最终诠释高度=的getHeight(),宽度=的getWidth();
        如果(高度= 0&放大器;!&安培;!WIDTH = 0)
            drawContent(宽度,高度);
    }

    公共无效setImageResource(最终诠释imageResId,最终诠释的backgroundColor){
        resetValues​​State(真正的);
        而(getCurrentView()!= mImageView)
            showNext();
        mImageResId = imageResId;
        this.mBackgroundColor =的backgroundColor;
        最终诠释高度=的getHeight(),宽度=的getWidth();
        如果(高度= 0&放大器;!&安培;!WIDTH = 0)
            drawContent(宽度,高度);
    }

    公共无效setImageBitmap(最终点阵位图){
        setImageBitmapAndBackgroundColor(位图,0);
    }

    公共无效setImageBitmapAndBackgroundColor(最后的位图的位图,最终诠释的backgroundColor){
        resetValues​​State(真正的);
        而(getCurrentView()!= mImageView)
            showNext();
        this.mBackgroundColor =的backgroundColor;
        mBitmap =位图;
        最终诠释高度=的getHeight(),宽度=的getWidth();
        如果(高度= 0&放大器;!&安培;!WIDTH = 0)
            drawContent(宽度,高度);
    }

    私人无效resetValues​​State(最终布尔alsoResetViews){
        mBackgroundColor = mImageResId = 0;
        mBitmap = NULL;
        多行文字= NULL;
        如果(alsoResetViews){
            mTextView.setText(空);
            mTextView.setBackgroundDrawable(空);
            mImageView.setImageBitmap(空);
            mImageView.setBackgroundDrawable(空);
        }
    }

    公共ImageView的getImageView(){
        返回mImageView;
    }

    公众的TextView getTextView(){
        返回mTextView;
    }

}
 

3.I've找到了一个不错的库,这样做,叫 PagerSlidingTabStrip 。没有找到样式本机之一的正式途径,虽然。

另一种方法是看谷歌的样本是Android的Studio中可用的权利,而被称为SlidingTabLayout。它显示了它是如何做。

编辑:为#3更好库 此处 ,被称为PagerSlidingTabStrip太

Background

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

The problem

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

This consists of 3 main components:

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

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

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

What I've found

  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.

  2. 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.

    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.

  3. 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.

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

The question

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

More specifically:

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

  2. 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?

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


Github project

EDIT: for #1 and #2, I've made a project on Github, here. Sadly I've also found an important bug, so I've also published about it here.

解决方案

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

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.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.I've found a nice library that does it, called PagerSlidingTabStrip . Didn't find an official way to style the native one, though.

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.

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

这篇关于如何模仿的ListView stickey项像棒棒糖的联系人应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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