Как добавить разделители в LinearLayoutICS?

Задний план

Я пытаюсь переключить свой альтернативный "Диспетчер приложений" " приложение из библиотека ActionBarSherlock в библиотека поддержки Google создала, так как она получает больше обновления (ActionBarSherlock больше не разрабатывается, ссылка здесь ), и я думаю, что он должен охватывать множество функций.

Эта проблема

Все прошло хорошо (или так кажется), за исключением класса с именем ICSLinearLayout в ActionBarSherlock, который я использовал для отображения разделителей, теперь он называется LinearLayoutICS.

Он просто не показывает разделители:

введите здесь описание изображения

Примечание: прежде чем вы спросите «почему бы вам просто не использовать GridView?», вот причина, а также this на случай, если я когда-нибудь захочу добавить заголовки.

Код

Код примерно такой же, как я использовал для 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...

Вопрос

Как я могу использовать этот класс для поддержки отображения разделителей на всех поддерживаемых версиях ОС библиотеки поддержки?

Что не так с кодом, который я написал?


person android developer    schedule 21.03.2014    source источник


Ответы (1)


Хорошо, похоже setShowDividers< /a> и setDividerDrawable нельзя использовать, потому что LinearLayoutICS не имеет их.

Мало того, Lint не предупредил меня об использовании.

Итак, в итоге я скопировал код LinearLayoutICS (из здесь, надеюсь, это последняя версия) и некоторые из исходный код LinearLayout, чтобы сделать что-то, что действительно работает. Я надеюсь, что у него нет никаких ошибок.

Да здравствует открытый исходный код... :)

К сожалению, setMeasureWithLargestChildEnabled недоступен для старых API, поэтому я думаю, что способ ActionBarSherlock все же лучше, если вы хотите его использовать.

РЕДАКТИРОВАТЬ: метод setMeasureWithLargestChildEnabled не работает с ActionBarSherlock.

Вот код, для тех, кто хочет использовать. Я надеюсь, что в следующий раз, когда библиотека будет обновлена, я не забуду проверить эту проблему еще раз.

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;
    }
  }
person android developer    schedule 21.03.2014