如何向 LinearLayoutICS 添加分隔线? [英] How to add dividers to LinearLayoutICS?

查看:32
本文介绍了如何向 LinearLayoutICS 添加分隔线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我正在尝试切换我的 原因,还有 这个,以防我想添加标题.

代码

代码与我用于 ActionBarSherlock 的代码大致相同:

rowLayout=new LinearLayoutICS(_context,null);rowLayout.setMeasureWithLargestChildEnabled(true);rowLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);rowLayout.setDividerDrawable(_context.getResources().getDrawable(R.drawable.list_divider_holo_dark));rowLayout.setOrientation(LinearLayout.HORIZONTAL);...//添加视图、布局参数等...

问题

我如何使用这个类来支持在支持库的所有支持的操作系统版本上显示分隔符?

我写的代码有什么问题?

解决方案

OK,好像 setShowDividerssetDividerDrawable 不能使用,因为 LinearLayoutICS 没有它们.

不仅如此,Lint 也没有警告我使用它.

所以,我最终得到的是复制 LinearLayoutICS 代码(来自 这里,希望是最新版本)和一些原始的 LinearLayout 代码,以制作一些确实有效的东西.我希望它没有任何错误.

开源万岁... :)

遗憾的是setMeasureWithLargestChildEnabled 不适用于旧的 API,所以我认为 ActionBarSherlock 方式仍然更好,以防万一您希望使用.

setMeasureWithLargestChildEnabled 方法不适用于 ActionBarSherlock.

这是代码,供希望使用的人使用.我希望下次图书馆更新时,我会记得再次检查这个问题.

public class LinearLayoutICS extends LinearLayout{私有 Drawable mDivider;私人 int mDividerWidth,mDividerHeight;私人 int mShowDividers;私人 int mDividerPadding;公共 LinearLayoutICS(最终上下文上下文,最终 AttributeSet attrs){超级(上下文,属性);//R 来自 "android.support.v7.appcompat.R" .最终 TypedArray a=context.obtainStyledAttributes(attrs,R.styleable.LinearLayoutICS);mDivider=a.getDrawable(R.styleable.LinearLayoutICS_divider);如果(mDivider!=空){mDividerWidth=mDivider.getIntrinsicWidth();mDividerHeight=mDivider.getIntrinsicHeight();}否则 mDividerHeight=mDividerWidth=0;mShowDividers=a.getInt(R.styleable.LinearLayoutICS_showDividers,SHOW_DIVIDER_NONE);mDividerPadding=a.getDimensionPixelSize(R.styleable.LinearLayoutICS_dividerPadding,0);a.recycle();setWillNotDraw(mDivider==null);}@覆盖受保护的无效 onDraw(最终 Canvas 画布){如果(getOrientation()==垂直)drawDividersVertical(画布);否则 drawDividersHorizo​​ntal(canvas);}@覆盖protected void measureChildWithMargins(final View child,final int parentWidthMeasureSpec,final int widthUsed,final int parentHeightMeasureSpec,final int heightUsed){如果(mDivider!=空){最终 int childIndex=indexOfChild(child);最终 int count=getChildCount();最终 LayoutParams params=(LayoutParams)child.getLayoutParams();//为了显示子视图之间的分隔线,我们修改它们的边距//创造空间.如果(getOrientation()==垂直){if(hasDividerBeforeChildAt(childIndex))params.topMargin=mDividerHeight;else if(childIndex==count-1&&hasDividerBeforeChildAt(count))params.bottomMargin=mDividerHeight;}否则 if(hasDividerBeforeChildAt(childIndex))params.leftMargin=mDividerWidth;else if(childIndex==count-1&&hasDividerBeforeChildAt(count))params.rightMargin=mDividerWidth;}super.measureChildWithMargins(child,parentWidthMeasureSpec,widthUsed,parentHeightMeasureSpec,heightUsed);}void drawDividersVertical(最终 Canvas 画布){最终 int count=getChildCount();for(int i=0;i=0;i--)if(getChildAt(i).getVisibility()!=GONE){hasVisibleViewBefore=true;休息;}返回 hasVisibleViewBefore;}返回假;}@覆盖public int getDividerPadding(){返回 mDividerPadding;}@覆盖公共无效setDividerPadding(最终intdividerPadding){mDividerPadding=dividerPadding;}@覆盖public void setShowDividers(final int showDividers){如果(mShowDividers!=showDividers)请求布局();mShowDividers=showDividers;}@覆盖public void setDividerDrawable(最终可绘制分隔符){如果(divider==mDivider)返回;mDivider=分频器;如果(除法器!=空){mDividerWidth=divider.getIntrinsicWidth();mDividerHeight=divider.getIntrinsicHeight();}别的{mDividerWidth=0;mDividerHeight=0;}setWillNotDraw(divider==null);请求布局();}@覆盖public Drawable getDividerDrawable(){返回 mDivider;}}

Background

I'm trying to switch my alternative "App Manager" app from ActionBarSherlock library to the support library Google has created, since it gets more updates (ActionBarSherlock is no longer being developed, link here ) and I think it should cover a lot of functionality.

The problem

All went well (or so it seems), except for a class named ICSLinearLayout on ActionBarSherlock I've used to show dividers on, that is now called LinearLayoutICS .

It just doesn't show the dividers:

Note: before you ask "why don't you just use a GridView?", here's the reason, and also this, in case I'd ever want to add headers.

The code

The code is about the same as I've used for ActionBarSherlock:

rowLayout=new LinearLayoutICS(_context,null);
rowLayout.setMeasureWithLargestChildEnabled(true);
rowLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
rowLayout.setDividerDrawable(_context.getResources().getDrawable(R.drawable.list_divider_holo_dark));
rowLayout.setOrientation(LinearLayout.HORIZONTAL);
... // add views, layout params, etc...

The question

How can I use this class in order to support showing dividers on all supported OS versions of the support library?

What is wrong with the code I've written?

解决方案

OK, it seems setShowDividers and setDividerDrawable cannot be used because LinearLayoutICS doesn't have them .

Not only that, but Lint didn't warn me about it being used.

So, what I ended up with is copying LinearLayoutICS code (from here, hope it's the latest version) and some of the original LinearLayout code, to make something that does work. I hope it doesn't have any bugs.

Long live open source ... :)

Sadly setMeasureWithLargestChildEnabled isn't available for old APIs, so I think the ActionBarSherlock way is still better in case that's something you wish to use.

EDIT: the setMeasureWithLargestChildEnabled method doesn't work on ActionBarSherlock.

Here's the code, for those who wish to use. I hope next time the library gets updated, I will remember to check this issue again.

public class LinearLayoutICS extends LinearLayout
  {
  private Drawable mDivider;
  private int      mDividerWidth,mDividerHeight;
  private int      mShowDividers;
  private int      mDividerPadding;

  public LinearLayoutICS(final Context context,final AttributeSet attrs)
    {
    super(context,attrs);
    // the R is from "android.support.v7.appcompat.R" .
    final TypedArray a=context.obtainStyledAttributes(attrs,R.styleable.LinearLayoutICS);
    mDivider=a.getDrawable(R.styleable.LinearLayoutICS_divider);
    if(mDivider!=null)
      {
      mDividerWidth=mDivider.getIntrinsicWidth();
      mDividerHeight=mDivider.getIntrinsicHeight();
      }
    else mDividerHeight=mDividerWidth=0;
    mShowDividers=a.getInt(R.styleable.LinearLayoutICS_showDividers,SHOW_DIVIDER_NONE);
    mDividerPadding=a.getDimensionPixelSize(R.styleable.LinearLayoutICS_dividerPadding,0);
    a.recycle();
    setWillNotDraw(mDivider==null);
    }

  @Override
  protected void onDraw(final Canvas canvas)
    {
    if(getOrientation()==VERTICAL)
      drawDividersVertical(canvas);
    else drawDividersHorizontal(canvas);
    }

  @Override
  protected void measureChildWithMargins(final View child,final int parentWidthMeasureSpec,final int widthUsed,final int parentHeightMeasureSpec,final int heightUsed)
    {
    if(mDivider!=null)
      {
      final int childIndex=indexOfChild(child);
      final int count=getChildCount();
      final LayoutParams params=(LayoutParams)child.getLayoutParams();
      // To display the dividers in-between the child views, we modify their margins
      // to create space.
      if(getOrientation()==VERTICAL)
        {
        if(hasDividerBeforeChildAt(childIndex))
          params.topMargin=mDividerHeight;
        else if(childIndex==count-1&&hasDividerBeforeChildAt(count))
          params.bottomMargin=mDividerHeight;
        }
      else if(hasDividerBeforeChildAt(childIndex))
        params.leftMargin=mDividerWidth;
      else if(childIndex==count-1&&hasDividerBeforeChildAt(count))
        params.rightMargin=mDividerWidth;
      }
    super.measureChildWithMargins(child,parentWidthMeasureSpec,widthUsed,parentHeightMeasureSpec,heightUsed);
    }

  void drawDividersVertical(final Canvas canvas)
    {
    final int count=getChildCount();
    for(int i=0;i<count;i++)
      {
      final View child=getChildAt(i);
      if(child!=null&&child.getVisibility()!=GONE&&hasDividerBeforeChildAt(i))
        {
        final LayoutParams lp=(LayoutParams)child.getLayoutParams();
        drawHorizontalDivider(canvas,child.getTop()-lp.topMargin);
        }
      }
    if(hasDividerBeforeChildAt(count))
      {
      final View child=getChildAt(count-1);
      int bottom=0;
      if(child==null)
        bottom=getHeight()-getPaddingBottom()-mDividerHeight;
      else bottom=child.getBottom();
      drawHorizontalDivider(canvas,bottom);
      }
    }

  void drawDividersHorizontal(final Canvas canvas)
    {
    final int count=getChildCount();
    for(int i=0;i<count;i++)
      {
      final View child=getChildAt(i);
      if(child!=null&&child.getVisibility()!=GONE&&hasDividerBeforeChildAt(i))
        {
        final LayoutParams lp=(LayoutParams)child.getLayoutParams();
        drawVerticalDivider(canvas,child.getLeft()-lp.leftMargin);
        }
      }
    if(hasDividerBeforeChildAt(count))
      {
      final View child=getChildAt(count-1);
      int right=0;
      if(child==null)
        right=getWidth()-getPaddingRight()-mDividerWidth;
      else right=child.getRight();
      drawVerticalDivider(canvas,right);
      }
    }

  void drawHorizontalDivider(final Canvas canvas,final int top)
    {
    mDivider.setBounds(getPaddingLeft()+mDividerPadding,top,getWidth()-getPaddingRight()-mDividerPadding,top+mDividerHeight);
    mDivider.draw(canvas);
    }

  void drawVerticalDivider(final Canvas canvas,final int left)
    {
    mDivider.setBounds(left,getPaddingTop()+mDividerPadding,left+mDividerWidth,getHeight()-getPaddingBottom()-mDividerPadding);
    mDivider.draw(canvas);
    }

  /**
   * Determines where to position dividers between children.
   *
   * @param childIndex Index of child to check for preceding divider
   * @return true if there should be a divider before the child at childIndex
   * @hide Pending API consideration. Currently only used internally by the system.
   */
  protected boolean hasDividerBeforeChildAt(final int childIndex)
    {
    if(childIndex==0)
      return (mShowDividers&SHOW_DIVIDER_BEGINNING)!=0;
    else if(childIndex==getChildCount())
      return (mShowDividers&SHOW_DIVIDER_END)!=0;
    else if((mShowDividers&SHOW_DIVIDER_MIDDLE)!=0)
      {
      boolean hasVisibleViewBefore=false;
      for(int i=childIndex-1;i>=0;i--)
        if(getChildAt(i).getVisibility()!=GONE)
          {
          hasVisibleViewBefore=true;
          break;
          }
      return hasVisibleViewBefore;
      }
    return false;
    }

  @Override
  public int getDividerPadding()
    {
    return mDividerPadding;
    }

  @Override
  public void setDividerPadding(final int dividerPadding)
    {
    mDividerPadding=dividerPadding;
    }

  @Override
  public void setShowDividers(final int showDividers)
    {
    if(mShowDividers!=showDividers)
      requestLayout();
    mShowDividers=showDividers;
    }

  @Override
  public void setDividerDrawable(final Drawable divider)
    {
    if(divider==mDivider)
      return;
    mDivider=divider;
    if(divider!=null)
      {
      mDividerWidth=divider.getIntrinsicWidth();
      mDividerHeight=divider.getIntrinsicHeight();
      }
    else
      {
      mDividerWidth=0;
      mDividerHeight=0;
      }
    setWillNotDraw(divider==null);
    requestLayout();
    }

  @Override
  public Drawable getDividerDrawable()
    {
    return mDivider;
    }
  }

这篇关于如何向 LinearLayoutICS 添加分隔线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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