Androidçšã®ã¡ãŒã«ã¢ããªã±ãŒã·ã§ã³ã®éçºäžãMail.Ruã§ã¯ãããã°ã©ã å
ã®ãšã³ããŠãŒã¶ãŒã«ãšã£ãŠããã²ãŒã·ã§ã³ãã©ãã»ã©äŸ¿å©ã§ããããåæããããšããããããŸãã ã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³ã䜿çšãããã¹ãŠã®äººããçŽæçã§é«éãªããã²ãŒã·ã§ã³ãæäŸããªã補åã¯ããããåŠçãã補åã«ãšã£ãŠå€±ãããããšãç¥ã£ãŠããããããããã©ãã»ã©éèŠãã説æãã䟡å€ã¯ãªããšæããŸãã å©äŸ¿æ§ãšæ
éã«èãæãããããã²ãŒã·ã§ã³ã¯ããŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ãæ°ã«å
¥ã£ãŠãããããæ¯åãåºã§æºåž¯é»è©±ãå£ããªãããã«ä¿¡ããããªãã»ã©ã®åªåãèŠããŸãã
ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãAndroidã®å
¬åŒuiãã¿ãŒã³ã«å«ãŸããåãããã¹ã©ã€ãã¡ãã¥ãŒãã䜿çšããŠããŸããã ãŠãŒã¶ããªãã£ã©ãã§ã®ããã€ãã®èª¿æ»ã®åŸããŠãŒã¶ãŒã«ããè¯ããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸããããã«ããµã€ãã¡ãã¥ãŒã«é²ãã§æ¹åããå¿
èŠããããšå€æããŸããã
ã ããããã€ã³ãã«è¿ãã ãã©ã«ããŒãšã¢ã«ãŠã³ããå«ããã©ã°ã¡ã³ããæåã®ãªã¹ããã¹ã¯ã€ãããŠäžç·ã«ç§»åãããããªã¡ãã¥ãŒã§ã¯ãªãã次ã®ããŒãžã衚瀺ããããã«ç§»åããã·ãŒãã®ã¹ã¿ãã¯ãªã©ããã©ã°ã¡ã³ããé çªã«ç§»åãããããšèããŸããã



SlideStackViewãšåŒã°ããã³ã³ãããŒã«ã®åäœã«å ããŠãéçºåŽãšè£œååŽã®äž¡æ¹ããããã«ããã€ãã®èŠä»¶ããããŸããã
1.åã¹ã©ã€ãã¯ãã©ã°ã¡ã³ãã§è¡šãå¿
èŠããããŸã
2.ãããŠã³ããªãŒããŒã¹ã¯ããŒã«å¹æããå®è£
ããå¿
èŠããããŸã-ã¹ã©ã€ãã端ãã匟åãããå Žå
3.ã¹ã©ã€ãå
ã®åçŽãªã¹ãã¯ãåäœã®äžå
·åãªãã§ã¹ã¯ããŒã«ããã¯ãã§ãã
4.ä¿åäž\埩å
ç¶æ
ïŒéããŠããã¹ã©ã€ãã®äœçœ®ãªã©ïŒ
åœç¶ã2çªç®ã®èŠä»¶ãæºããåã«ãViewGroupèªäœãå®è£
ããå¿
èŠããããŸããViewGroupã¯ãæå³ãããšããã«åã管çããŸãã
åçŽãªãã®ããè€éãªãã®ãžãšç§»è¡ããŸãããŸããandroidFrameworkã«ã¢ã¯ã»ã¹ããæ¹æ³ã決å®ããå¿
èŠããããŸããããã«ããããŸãèªè»¢è»ãäœæããã次ã«ãæãé¡äŒŒãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸããŸãã ã¹ã©ã€ãã®é
眮ã¢ãã«ãå®å
šã«ç°ãªããããäžèšã®ViewPagerã¯æ©èœããŸããã ãããã£ãŠãéå±€ãæ€çŽ¢ããViewGroupã§åæ¢ããŸãã
public class SlideStackView extends ViewGroup{ public SlideStackView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); ... initAttributes(context, attrs);
ããã§ç¹å¥ãªããšã¯ãã¹ã©ã€ããæããšãã«éæšæºã®é åºã䜿çšããããã«æ±ããŠããããšã ãã§ãã æåã¯æ··ä¹±ããå¯èœæ§ããããŸãã åé¡ã¯ãã¹ã©ã€ãã«å³ããå·Šã«çªå·ãä»ããå¿
èŠãããããšã§ãã æåïŒïŒ0ïŒã®ãªã¹ãã«è¡ãããã«æåã®ã¹ã©ã€ããè¿ãããã¯ãæã
ã¯ãã©ã«ãïŒïŒ1ïŒã®ãªã¹ããã¹ã©ã€ãããæåŸã«æã
ã¯ã¢ã«ãŠã³ãïŒïŒ2ïŒã®ãªã¹ãã§ã¹ã©ã€ããåç
§ããŠãã ãããåç
§ããŠãã ããã ViewGroupèªäœã®çªå·ä»ãã§ã¯ãéåžžã®é åºã䜿çšããæ¹ãã¯ããã«äŸ¿å©ã§ããã€ãŸããã¹ã©ã€ããè¿œå ãããšããããã«ã¹ã©ã€ããããã«æç»ãé
眮ãããšããªã©ãå·Šããå³ãžã®é åºã§ãã ããã§ã®ãã€ã³ãã¯ããããæ
£ç¿çã§ãããšããããšã§ããªãã1è¡æªæºã®ã³ãŒãã§èšè¿°ããå¿
èŠããããšããããšã§ãã å®éããã¹ãŠã¯MotionEventsã®åŠçã«äŸåããŠããŸãã ãããã転éããããšãåã®é
åã0ããchildCountã®é ã«æž¡ãããŸãã äžéšã®ã¹ã©ã€ããäžéšãšéãªãå¯èœæ§ãããå Žåãéä¿¡ãããMotionEventãåŠçã§ããã¹ã©ã€ããæ¢ããŠãåãäžéšããäžéšãžã¯ããŒã«ãå§ããå¿
èŠããããŸãã ããã«ã€ããŠã¯ãMotionEventã®åŠçãéå§ãããšãã«è©³ãã説æããŸãã
ãããã£ãŠãéåžžã«é »ç¹ã«ãã®ã¡ãœãããå¿
èŠã§ãã
private View getChild(int position){ return getChildAt(getChildCount() - 1 - position); }
次ã«ãæç»é åºã§ã¯ãäœãå€æŽããå¿
èŠã¯ãããŸããã
@Override protected int getChildDrawingOrder(int childCount, int i) {
ä»ãã楜ããéšåã§ãã ãã¡ãããã¹ã©ã€ãã衚瀺ããäºå®ã§ããã¹ã©ã€ãã®æ°ã¯ããŸããŸã§ãã Android Framework Teamã§ã¯ããã®ããã«ããããã¢ããã¿ãŒã䜿çšããããšã決å®ããŸãããããã¯åªããã¢ãããŒããªã®ã§ã䜿çšããŸãã ãããŠãç§ãã¡ã«æãè¿ãã®ã¯ãViewPagerã§äœ¿çšãããã¢ããã¿ãŒã®å®è£
ã ãã§ãããã®ã¢ããã¿ãŒã«ã¯è¿œå ã®å€æŽãå¿
èŠã§ãããããã«ã€ããŠã¯åŸã§ããã«èª¬æããŸãã
static final int INVALID_POSITION = -1; private int mFirst; private int mSelected; private SlideStateAdapter mAdapter; private final DataSetObserver mObserver = new Observer(); public void setAdapter(SlideStateAdapter adapter){ if (mAdapter != null){ mAdapter.unregDataSetObserver(mObserver); mFirst = INVALID_POSITION; mScroller.stopScrolling(); removeAllViews(); } if(adapter != null){ mAdapter = adapter; mAdapter.regDataSetObserver(mObserver); } }
ã¯ã©ã¹ãªãã¶ãŒããŒã¯ãåå¿è
ã«ãšã£ãŠæ¬¡ã®ããã«ãªããŸãã
private final class Observer extends DataSetObserver{ @Override public void onChanged() {
ããã§ã衚瀺ããå
容ãšãããè¡ãæ¹æ³ã®éã®ãªã³ã¯ãšããŠæ©èœããã¢ããã¿ãŒãã§ããŸããã
æããã«ããã®çš®ã®ã³ã³ãããŒã«ã®éèŠãªãã€ã³ãã®1ã€ã¯ãã¹ã©ã€ããSlideStackViewå
ã§ã©ã®ããã«ç§»åãããã§ãã ããã¯ãå²ãåœãŠãããæ©èœãšãã®ã¿ã¹ã¯ã®å¹æçãªå®è£
ã«å¿
èŠãªã³ãŒãã®éã®äž¡æ¹ã®ç¹ã§ãããªãèšå€§ãªã¿ã¹ã¯ã§ãã ãããã£ãŠã次ã®è§£æ±ºçã¯ãã¹ã¯ããŒã«åŠçã«é¢é£ãããã¹ãŠã®æ©èœãããã®ããã«åŒã³åºãããã¯ã©ã¹ã«ç§»åããããšã§ãã
public static class SlideScroller extends Scroller implements OnTouchListener{ private final ScrollingListener mListener; private final GestureDetector mGestureDetector; public SlideScroller(Context context, ScrollingListener listener, OnGestureListener gestureListener) { super(context); this.mListener = listener; this.mGestureDetector = new GestureDetector(context, gestureListener); mGestureDetector.setIsLongpressEnabled(false); } public void scroll(int distance, int time) {
ããã§ããã®ã¢ãžã¥ãŒã«ã®ã¹ã¯ããŒã«ãããã³å
šäœãå®å
šã«åãåºããScrollingListenerãä»ããŠSlideStackViewã«å¿
èŠãªã€ãã³ãã®ã¿ãéç¥ã§ããŸãã
public interface ScrollingListener { void onScroll(int distance); void onStarted(); void onFinished(); void onJustify(); }
ViewGroupã®å®è£
ã¯ã©ãããå§ãŸããŸããïŒ ViewGroupã¯ãViewã§ã§ããããšã«å ããŠããã®äžã«ä»ã®ãã¥ãŒãæã€ããšãã§ãããªã³ã«ãŒã§ãã ãããã£ãŠãç§ãã¡ã®è³ªåã«å¯Ÿããçãã¯ãViewGroupã®å®è£
ã§ãããããã¯Overrideã¡ãœããã§å§ãŸããŸãã
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { }
ã¹ã©ã€ããé
眮ããå ŽæïŒ
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { }
ãããŠãã¹ã©ã€ãã枬å®ããå Žæã
枬å®ããå§ããŸãããïŒ
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)); int childHeightSize = getMeasuredHeight(); int mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec( childHeightSize, MeasureSpec.EXACTLY);
ããã§ã¯ãã¹ãŠãç°¡åã§ããæåã«ãã³ã³ããããäžããããä»æ§ã«åºã¥ããŠã¹ã©ã€ãã¹ã¿ãã¯ã®ãµã€ãºãèšå®ããŸãã ã¢ãã€ã«ã¡ãŒã«ã§ã¯ãã¹ã©ã€ãã¹ã¿ãã¯ãããŒã¯ã¢ããã®ã«ãŒãèŠçŽ ã§ããããããã®æ¹æ³ã§å©çšå¯èœãªé åå
šäœãåããŸãã
ãªããªã ã¹ã©ã€ãã®é«ããå€ããããªãå Žåã¯ãMeasureSpec.EXACTLYãã©ã°ãšãã¹ã©ã€ãã¹ã¿ãã¯ã®æž¬å®ãããé«ãã«çããå€ã䜿çšããŠãé«ãã®ä»æ§ãäœæããŸãã
ã¹ã©ã€ãã枬å®ããã«ã¯ãåœç¶ã¹ã©ã€ãèªäœãå¿
èŠãªã®ã§ãããããæ¢ã«ããŒã¯ã¢ããã«è¿œå ãããŠããããšã確èªããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãã¹ã©ã€ããäžããäžã«åããŸãã ãã®åŸãã¹ã©ã€ãã調ã¹ãŠãç®çã®å¹
ã決å®ããchild.measureïŒwidthSpecãmChildHeightMeasureSpecïŒãåŒã³åºããŠæž¬å®ããŸãã
ã¹ã©ã€ãã®å¹
ã¯ãã¹ã©ã€ãã¹ã¿ãã¯ã®å¹
ããç¹å®ã®ã¹ã©ã€ãïŒãã©ã«ããŒã®ãªã¹ããå«ãã¹ã©ã€ããªã©ïŒã®å·Šå³ã®ã€ã³ãã³ããåŒãããã®ãšããŠå®çŸ©ãããŸãã

ã¹ã©ã€ãã枬å®ããåŸã¯ãæ£ããé
眮ããã ãã§ãã
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { mInLayout = true; fillViewsIn(); mInLayout = false; for (int i = 0; i < getChildCount(); i++) { View child = getChild(i); int position = i + mFirst; onLayoutChild(child, position, changed); } mDirty.setEmpty(); } protected void onLayoutChild(View child, int position, boolean changed) { if (child.getVisibility() != GONE) { LOG.d("onLayoutChild " + position); if (position < mSelected && changed){ closeView(position); LOG.v("close slide at " + position); } final LayoutParams lp = (LayoutParams) child.getLayoutParams(); SlideInfo info = getSlideInfo(child); int childLeft = getLeftEdge(position) + info.mOffset; int childRight = getRightEdge(position - 1) + info.mOffset; int childTop = getTop(); if (lp.needsMeasure) { lp.needsMeasure = false; final int widthSpec = MeasureSpec.makeMeasureSpec( childRight - childLeft, MeasureSpec.EXACTLY); final int heightSpec = MeasureSpec.makeMeasureSpec( getMeasuredHeight(), MeasureSpec.EXACTLY); child.measure(widthSpec, heightSpec); }
æåã«ãããŒã¯ã¢ããã«è¡šç€ºã§ãããã¹ãŠã®ã¹ã©ã€ããæ¢ã«è¿œå ãããŠããããšã確èªããå¿
èŠããããŸãã次ã«ãç¹å®ã®åäœçœ®ã«ã¹ã©ã€ãã®äœçœ®ãçŽæ¥èšå®ããŸãã è¿œå ããã°ããã®ã¹ã©ã€ããéããããªãå¯èœæ§ããããšããäºå®ãèæ
®ããããšãéèŠã§ã;ãããä¿®æ£ããå¿
èŠããããŸãã
ãŸããã¹ã©ã€ãã¹ã¿ãã¯ã®æž¬å®åŸã«ã¹ã©ã€ããè¿œå ããå Žåããã®ã¹ã©ã€ãã枬å®ããå¿
èŠããããŸãã
ããã§ãSlideInfoã¯ãã¹ã©ã€ãã®äœçœ®ãšç¶æ
ã«é¢ããæ
å ±ãå«ãéåžžã®ãã«ããŒã§ãã
public static final class SlideInfo implements Parcelable{ private int mOffset = 0; private boolean mOpened = true; private int mPosition = INVALID_POSITION; private Drawable mSpace; public SlideInfo() { super(); } }
å®éãSlideInfoãåå¥ã«äœ¿çšãã代ããã«ãLayoutParamsã¯ã©ã¹ã®çžç¶äººã«å¯ŸåŠããããšãã§ããŸããããã¯æçµçã«ã¯å°æ¥ã䜿çšããŸãã å·çæç¹ã§ã¯ããããç¥ããŸããã§ããããçŸåšãã®æ
å ±ãlayoutParamsã«è»¢éããŠããŸããããããã«ããããããããšæããŸãã è¿œå ãã«ããŒã«ã¯ç¯çœªè
ã¯ããŸããããç§ã¯KISSïŒKeep It Simple StupidïŒã¢ãããŒãã®æ¯æè
ã§ããã2ã€ã§ã¯ãªã1ã€ã®ãªããžã§ã¯ãã䜿çšããæ¹ãã¯ããã«ç°¡åã§ã:)
ããã§ãViewGroupã«æ¢ã«è¿œå ããã¹ã©ã€ããã©ã®ããã«æ±ãããèããŸããã ãŸã æ€èšãããŠããªã質åã¯ãããã«ããããè¿œå ããæ¹æ³ã§ãã ãã®ãããã¡ãœãããæ®ããŸããïŒ
private void fillViewsIn() { int position = 0; int left = 0; if (getChildCount() > 0){ position = getLastVisiblePosition() + 1; View lastView = getChild(position - mFirst - 1); left = lastView.getLeft() - lastView.getScrollX(); } addViewsInside(position, left); adjustViewsVisibility(); }
ãã®ã¡ãœããã¯ãæåŸã®ã¹ã©ã€ããæ€çŽ¢ãã次ã®ã¹ã©ã€ããããã°SlideStackViewã«è¿œå ãããŠãŒã¶ãŒã«è¡šç€ºãããŸãã ããã¯ãã¹ãŠãã®ããã«èµ·ãããŸãïŒ
private void addViewsInside(int position, int left) { if (mAdapter == null || mAdapter.getCount() == 0){ return; } mAdapter.startUpdate(this); while ((position <= mSelected + 1 || left > getLeft()) && position < mAdapter.getCount()){ if (mFirst == INVALID_POSITION){ mFirst = 0; } LOG.d("addView inside " + position + " mSelected " + mSelected); mAdapter.instantiateItem(this, position); left = mSelected > position ? getLeftEdge(position) : getRightEdge(position - 1); position ++; } mAdapter.finishUpdate(this); }
ã¹ã©ã€ããšããŠãã©ã°ã¡ã³ãã䜿çšããããšã«ããã®ã§ã1ã€ã®ãã©ã°ã¡ã³ããã©ã³ã¶ã¯ã·ã§ã³å
ã«ã¹ã©ã€ããè¿œå ããæ¹ãé©åã§ãã
ãã®åŸãã¢ã«ãŠã³ãã«æ°ããè¿œå ãããã¹ã©ã€ããåã£ãŠãåææ¡ä»¶ã®æ¹æ£ãè¡ããããã»ã¹ãç¹°ãè¿ããŠã¹ã©ã€ããããŸã§ã¹ã©ã€ããäœæããããäžè¶³ããããŸãã¯ã¹ã©ã€ãã¯ãèŠèªæ§ã®ã¹ã©ã€ãã¹ã¿ãã¯ã®å¢çãè¶ããŠè¡ãããšã¯ãããŸããã leftã<= getLeftïŒïŒã«ãªã£ãå Žåãããã¯è¿œå ããæåŸã®ã¹ã©ã€ããã¹ã¿ãã¯ã¹ã©ã€ãã®å¢çç·ãšéãªã£ãŠããããšãæå³ããŸãã 次ã®ã¹ã©ã€ããå®å
šã«ãã®ã¹ã©ã€ãã®äžã®ããããã§ããåŸãããŸãã¯å·Šã«èŠãããšãã§ãããããã®é åã¯ãã¹ã©ã€ãã¹ã¿ãã¯ã®å¢çå
ã«åãŸã£ãŠããªããšãŠãŒã¶ã衚瀺ãããŠããªãããšãããã®æ段ã ãããŠä»¥æ¥ ã¹ã©ã€ãã¯ãŠãŒã¶ãŒã«ã¯è¡šç€ºãããªããããè¿œå ããæå³ã¯ãŸã ãããŸããã
ãããããã¹ã©ã€ãèªäœã®è¿œå ã¯ã©ãã§ããïŒããšããªãã¯å°ããŸãã mAdapter.finishUpdateïŒããïŒãåŒã³åºããåŸ; ã¢ããã¿ã¯ãã©ã³ã¶ã¯ã·ã§ã³ãéå§ããFragmentManagerã¯è»¢éãããã³ã³ããïŒãã-ã€ãŸãSlideStackViewïŒãžã®ãã©ã°ã¡ã³ãã®è¿œå ãéå§ããŸãã ãã©ã°ã¡ã³ããè¿œå ããããã»ã¹ãäžèšã§èª¬æããã®ã¯é£ããã®ã§ãèªè
ãã¬ãã¥ãŒã§ããããã«ãã®ãããã¯ãæ®ããŸãããã ã¹ã©ã€ããæ£ããé
眮ããã«ã¯ãããã€ãã®èª¿æŽãå¿
èŠã«ãªãããããã®ã¡ãœãããåå®çŸ©ããŸãã
@Override public void addView(View child, int index, ViewGroup.LayoutParams params) { LOG.d("Add view from outside " + child); if (!checkLayoutParams(params)) { params = generateLayoutParams(params); } final LayoutParams lp = (LayoutParams) params; SlideInfo info = getSlideInfo(child); info.mPosition = getChildCount(); if (mAdapter != null){ info.mSpace = mAdapter.getSpaceDrawable(info.mPosition); } if (mInLayout) { lp.needsMeasure = true; addViewInLayout(child, 0, params); } else { super.addView(child, 0, params); } if (info.mPosition < mSelected){ closeView(info.mPosition); } }
å¿
èŠãªããŒã¿ãå
¥åããŸãã 次ã«ãã¬ã€ã¢ãŠãäžã«ã¹ã©ã€ããè¿œå ããããã©ããã«å¿ããŠãã¹ã¿ãã¯ãã¹ã©ã€ãã«è¿œå ãããã®äœçœ®ãçŸåšã¢ã¯ãã£ããªã¹ã©ã€ãã®äœçœ®ãããå°ããå Žåã¯ã¹ã©ã€ããéããŸãã
åœç¶ããã©ã°ã¡ã³ããã¹ã©ã€ãã¹ã¿ãã¯ã«è¿œå ããå Žåã¯ããã€ãããããåé€ããå¿
èŠããããŸãã åé€åäœã¯è¿œå ã«äŒŒãŠããŸããããŠãŒã¶ãŒã«è¡šç€ºãããªããªã£ãã¹ã©ã€ããæ¢ããã¢ããã¿ãŒã䜿çšããŠViewGroupããåé€ããã ãã§ãã
ã¡ãœããfillViewsInïŒïŒ; æåŸã®ä¿çäžã®è¡ãæ®ããããã§adjustViewsVisibilityã¡ãœãããåŒã³åºããŸãã
ãã®ã¡ãœããã¯ãååã瀺ãããã«ãã¹ã©ã€ãã®å¯èŠæ§ãä¿®æ£ããŸãã ããã¯ãããŒã¯ã¢ããããåé€ã§ããªããããŠãŒã¶ãŒã«ã¯è¡šç€ºãããªããªã£ãã¹ã©ã€ãã®æç»ã«æéãç¡é§ã«ããªãããã«å¿
èŠã§ãã ããèªäœã§ãèŠèªæ§ã®èª¿æŽã¯éåžžã«ç°¡åã§ã - æã
ã¯å¯äžView.setVisibilityïŒintåïŒããã¹ãŸãã¯View.VISIBLEããŸãã¯View.INVISIBLEãéããŠã¹ã©ã€ãã«å¯èŠæ§ã眮ããŸãã ã¡ãœããèªäœã¯å°ãè€éã«èŠããŸããããã®åäœã®åçãç解ãããšããã¹ãŠãæããã«ãªããŸãã
private void adjustViewsVisibility() { Rect drawingRect = new Rect(); drawingRect.left = getRight(); drawingRect.top = getTop(); drawingRect.right = getRight(); drawingRect.bottom = getTop() + getHeight(); Rect parent = getChildDrawingRectPositive(this); for (int i = 0; i < getChildCount(); i ++){ boolean hideNext = false;
ãã®ã¡ãœããã®åäœããã€ã³ãããããã«ãã§ããã ãç°¡åã«ã¹ãããããšã«è©Šã¿ãŸãã
äžè¬çãªã¢ã«ãŽãªãºã ã¯æ¬¡ã®ããã«ãªããŸãã
1.ã¹ã¿ãã¯ã¹ã©ã€ãã®å³ç«¯ãåããŸãïŒå³ç«¯ã®ã¹ã©ã€ãã¯åžžã«å®å
šã«è¡šç€ºãããå·ŠåŽã®ã¹ã©ã€ãã¯ãããšéãªã£ãŠããããã§ããéã«ãããã¯ã§ããŸããïŒã
2.ãã¹ãŠã®ã¹ã©ã€ãã調ã¹ãŠãåã¹ã©ã€ããå ããã¹ã©ã€ãã¹ã¿ãã¯å
ã®ã¹ããŒã¹ãå æãšãªã¢ã«è¿œå ããŸãã
3.åæã«ã次ã®ã¹ã©ã€ããã¹ã¿ãã¯ã¹ã©ã€ãã®å¢çå€ã«ãããããã®äžã«ããã¹ã©ã€ãã«ãã£ãŠå®å
šã«éããããŠãããã調ã¹ããé衚瀺ããšããŠããŒã¯ããŸãã ãã以å€ã®å Žåãã¹ã©ã€ãã¯ãå¯èŠããšèŠãªãããŸãã
äžèšã®drawingRectã¡ãœããã§ã¯ãããã¯ãŸãã«ã¹ã©ã€ãã§æ¢ã«å æãããŠããé åã§ãããchildRectã¯ã¹ã©ã€ããç¹å®ã®äœçœ®ã«ããé åã§ãã
圱ã®èª¿æŽãè¡ãå¿
èŠããããŸãã 圱ãèªåã§æç»ãããããã¹ã©ã€ãã®å¯èŠæ§ã調æŽãããšãã«ã圱ãå ããã¹ããŒã¹ãèæ
®ããªããšãã¹ã©ã€ããäºãã«è¡šç€º/é衚瀺ãããç¬éã«äžå¿«ãªç¹æ»
ãèŠãããŸãã åé¡ã¯ãæç»ããã»ã¹äžã«ViewGroupã§ãåã衚瀺ãããŠããã衚瀺ãããŠããªããã確èªããããšã§ãã 衚瀺ãããŠããªãå ŽåãdrawChildïŒCanvasãViewãlongïŒã¡ãœããã¯ãã®åã«å¯ŸããŠåŒã³åºãããŸãããããã¯éåžžã«è«ççã§ãã ãããã£ãŠãã¹ã©ã€ãããã¯åœ±ã ããèŠããå Žåã§ããã¹ã©ã€ããèŠããããã«ããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãè¿œå ã®ãã§ãã¯ãè¡ããã¹ã©ã€ãããŠãŒã¶ãŒã«è¡šç€ºãããªããšå€æããæç¹ã§ä¿®æ£ãè¡ããŸãã
Rect childShadow = getShadowRect(childRect); if (childShadow.isEmpty()){ hideNext = true; }
äžè¬ã«ãåœç¶ãªãããadjustViewsVisibilityïŒïŒã¡ãœããå
šäœãæé©åã®ããã«å®è£
ãããŠãããšããäºå®ã«æ³šæããããšãéèŠã§ãã çµå±ã®ãšããããŠãŒã¶ãŒã®ã¢ãã€ã«ããã€ã¹ã«ããŸã èŠããªãä»äºããããããªãã®ã§ãã ããã«ãäžå¿
èŠãªæç»ã¯ããã©ãŒãã³ã¹ã«å€§ãã圱é¿ããããã«å¿ããŠã¢ãã¡ãŒã·ã§ã³ãã¹ã ãŒãºã«ããŸãã
ãã ãããŠãŒã¶ãŒã«è¡šç€ºãããªãã¹ã©ã€ãã®æç»ãé²æ¢ããã ãã§ã¯ãåé¡ãå®å
šã«è§£æ±ºããããã§ã¯ãããŸããã ã¹ã©ã€ãã®ããªãŒããŒã¬ã€ãã¯ãŸã ãããŸãã ããã¯ã1ã€ã®ã¹ã©ã€ãã暪ã«ç§»åãããã®äžãã次ã®ã¹ã©ã€ãã®äžéšãèŠããšãã«çºçããŸãã ã€ãŸãããŠãŒã¶ãŒã«ã¯ã¹ã©ã€ãã®äžéšã®ã¿ïŒãŸãã¯ãã·ã£ããŠããã·ã£ããŠã®äžéšã®ã¿ïŒã衚瀺ãããã¹ã©ã€ãå
šäœãå
šäœãšããŠæç»ãããããšãããããŸãã ãã®åŸããã¡ããããã®äžã«å¥ã®ã¹ã©ã€ããæç»ããŸãã
å人çã«ãCanvas.clipRectïŒRectïŒã¡ãœããã䜿çšãã以å€ã«ããã®ãããªåé¡ã解決ããä»ã®æ¹æ³ã¯ç¥ããŸããã ãããã£ãŠãåã
ã®ãã¬ãŒã ã§ãŠãŒã¶ãŒãã¹ã©ã€ãã®ã©ã®éšåãèŠããã決å®ãããã£ã³ãã¹äžã«æç»ããé åããŠãŒã¶ãŒããã®ã¹ã©ã€ãããèŠãã¹ããŒã¹ã«å¶éããŠãããã¹ã©ã€ããæç»ããå¿
èŠããããŸãã
äžèšã®ã¹ã©ã€ãæç»æ¹æ³ã¯ãç§ã«ãšã£ãŠæ¬¡ã®ãããªãã®ã§ãã
@Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { Rect childClip = getChildClipRect(child);
ãã¹ãŠã¯ãã¹ã©ã€ãã®é·æ¹åœ¢ãèšç®ããããšããå§ãŸããŸããããã¯ãç»é¢äžã§ãŠãŒã¶ãŒã«è¡šç€ºããããã®åŸãã¹ã©ã€ãéã®ã¹ããŒã¹ãåããŠïŒååšããå ŽåïŒãã¹ã©ã€ãã®åœ±ãæç»ãããã®åŸãèšç®ãããchildClipã«ãã£ã³ãã¹ãå¶éããæç»ããŸãViewGroupã§å®çŸ©ãããŠãããšããã«ã¹ã©ã€ãããŸãã
ã芧ã®ãšããããã¹ãŠãéåžžã«ç°¡åã§ãã ãã¹ãŠã®éæ³ã¯ããã£ã³ãã¹ããåãæããå¿
èŠãããé åãæ°ããæ¹æ³ã®äžã«ãããŸãã
private Rect getChildClipRect(View child) { Rect childClip = getChildDrawingRectPositive(child); int position = getPositionForView(child); subtractRectWithChilds(childClip, position);
æåã®æ¹æ³ã§ã¯ãã¹ã©ã€ãã¹ã¿ãã¯å
ã®ã¹ã©ã€ãã®äœçœ®ãèŠã€ããŠãããã¹ã©ã€ãã¢ããã¿ãŒã®ã€ã³ããã¯ã¹ã§ãã®äœçœ®ãèŠã€ããŸãã ãã®åŸãäžèŠãªãã®ããã¹ãŠãæžç®ãããŠçµæãè¿ããŸãã
, «» . , , ( ).
, .
, , , .
private static boolean subtractToLeft(Rect source, Rect r){ boolean changed = subtract(source, r); if (!changed && source.contains(r)){
, , , «» - :)
, , â Rect. , . . , . «» , - , . , . . , , , . , , .
, , , , .
, â . , . , . , , MotionEvent' , , -, .
, , , ViewGroup.
â - Mail.Ru. . , .