
ããã«ã¡ã¯ãHabrïŒ å°ãåãåéºãæ°ãããããžã§ã¯ããæè¡ãæ¢ããŠãç§ã¯ ããããã«ãªããŸãã Redmadrobotã«å®äœããŸããã æ€
åãã¢ãã¿ãŒãMacbookããããŠãŠã©ãŒã ã¢ããçšã®å°ããªå
éšãããžã§ã¯ããæã«å
¥ããŸããã ãããžã§ã¯ãã§äœ¿çšããã¡ãã£ã¢ã³ã³ãã³ãã衚瀺ããã«ã¯ãèªå·±èšè¿°ã©ã€ãã©ãªã宿ãããŠå
¬éããå¿
èŠããããŸããã ãã®èšäºã§ã¯ã1é±éã§ã¿ããã€ãã³ããçè§£ãããªãŒãã³ãœãŒã¹ã«ãªããAndroid SDKã®ãã°ãèŠã€ããã©ã€ãã©ãªãå
¬éããæ¹æ³ã説æããŸãã
éå§ãã
ã¹ãã¢ã¢ããªã®éèŠãªæ©èœã®1ã€ã¯ãååããµãŒãã¹ã®åç»ãåçãããããåŽé¢ãã衚瀺ã§ããããšã§ãã è»èŒªãåçºæããããªãã£ãã®ã§ãç§ãã¡ã«åã£ã宿ããã©ã€ãã©ãªãæ¢ãã«è¡ããŸããã
ãŠãŒã¶ãŒã次ã®ããšãã§ããããã«ããã®ãããªãœãªã¥ãŒã·ã§ã³ãèŠã€ããããšãèšç»ããŸããã
- åçãèŠã;
- ãã³ãã䜿çšããŠåçãæ¡å€§çž®å°ããããã«ã¿ããããŸãã
- ãããªãèŠã
- ã¡ãã£ã¢ã³ã³ãã³ãã®å転ã
- 瞊ã«ã¹ã¯ã€ãããŠåçã«ãŒããéããŸãïŒã¹ã¯ã€ãããŠéããŸãïŒã
ç§ãã¡ãèŠã€ãããã®ã¯æ¬¡ã®ãšããã§ãã
- FrescoImageViewer-åçããã³åºæ¬çãªãžã§ã¹ãã£ãŒã®è¡šç€ºãšã¹ã¯ããŒã«ããµããŒãããŸããããããªã®è¡šç€ºã¯ãµããŒãããã Frescoã©ã€ãã©ãªã察象ãšããŠããŸãã
- PhotoView-åçã®è¡šç€ºããµããŒãããŸããã¹ã¯ããŒã«ãã¹ã¯ã€ãããŠéãã以å€ã®åºæ¬çãªã³ã³ãããŒã«ãžã§ã¹ãã£ã®ã»ãšãã©ã¯ããããªã®è¡šç€ºããµããŒãããŠããŸããã
- PhotoDraweeView-æ©èœã¯PhotoViewã«äŒŒãŠããŸãããFrescoçšã«èšèšãããŠããŸãã
èŠã€ãã£ãã©ã€ãã©ãªã¯ã©ããèŠä»¶ãå®å
šã«æºãããŠããªããããç¬èªã®ã©ã€ãã©ãªãäœæããå¿
èŠããããŸããã
峿žé€šãå®çŸããŸã
å¿
èŠãªæ©èœãååŸããããã«ãä»ã®ã©ã€ãã©ãªããæ¢åã®ãœãªã¥ãŒã·ã§ã³ã宿ãããŸããã 圌ãã¯äœãèµ·ãã£ãã®ãæ§ãããªååã®Androidã®ã£ã©ãªãŒãäžããããšã«ããŸããã
æ©èœãå®è£
ããŸã
åçã®è¡šç€ºãšãºãŒã
åçã衚瀺ããããã«ãPhotoViewã©ã€ãã©ãªã䜿çšããŸãããããã¯ãããã«äœ¿çšã§ããã¹ã±ãŒãªã³ã°ããµããŒãããŠããŸãã
ãããªãèŠã
ãããªãèŠãããã«ã圌ãã¯MediaPagerAdapterã§åå©çšãããExoPlayerãåããŸãã ã ãŠãŒã¶ãŒãåããŠãããªãéããšãExoPlayerãäœæãããŸãã å¥ã®èŠçŽ ã«åãæ¿ãããšãã¥ãŒã«å
¥ãããããããæ¬¡ã«ãããªãéå§ãããšãã«ãæ¢ã«äœæãããŠããExoPlayerã€ã³ã¹ã¿ã³ã¹ã䜿çšãããŸãã ããã«ãããèŠçŽ éã®ç§»è¡ãããã¹ã ãŒãºã«ãªããŸãã
ã¡ãã£ã¢ã³ã³ãã³ãã®ã¹ã¯ããŒã«
ããã§ã¯ãFrescoImageViewerã®MultiTouchViewPagerã䜿çšããŸããããããã¯ãã«ãã¿ããã€ãã³ããã€ã³ã¿ãŒã»ããããªãããããžã§ã¹ãã£ã远å ããŠç»åãæ¡å€§çž®å°ããããšãã§ããŸããã
ã¹ã¯ã€ãããŠéããŸã
PhotoViewã¯ãã¹ã¯ã€ããé衚瀺ã«ããŠãããŠã³ã¹ããµããŒãããŠããŸããïŒç»åãæ¡å€§ãŸãã¯çž®å°ãããšãã«å
ã®ç»åãµã€ãºã埩å
ããŸãïŒã
ãããã©ã®ããã«åŠçããããæ¬¡ã«ç€ºããŸãã
ã¿ããã€ãã³ããåŠç¿ããŠãã¹ã¯ã€ãããŠå®è£
ããŸã
ã¹ã¯ã€ãããµããŒãããŠåŽäžããåã«ãã¿ããã€ãã³ãã®ä»çµã¿ãçè§£ããå¿
èŠããããŸãã ãŠãŒã¶ãŒãç»é¢ã«è§ŠãããšãçŸåšã®ã¢ã¯ãã£ããã£ã§dispatchTouchEvent(motionEvent: MotionEvent)
ã¡ãœãããåŒã³åºããã MotionEvent.ACTION_DOWN
ãMotionEvent.ACTION_DOWN
ãŸãã ãã®ã¡ãœããã¯ãã€ãã³ãã®éåœã決å®ããŸãã ã¿ããåŠçã®ããã«motionEvent
ãonTouchEvent(motionEvent: MotionEvent)
ã«onTouchEvent(motionEvent: MotionEvent)
ããViewéå±€ã§äžããäžã«ããã«ããã·ã¥ã§ããŸãã ACTION_UP
ããåã®ã€ãã³ãããã³/ãŸãã¯åŸç¶ã®ã€ãã³ãã«é¢å¿ããããã¥ãŒã¯ãtrueãè¿ããŸãã
ãã®åŸããžã§ã¹ãã£ãACTION_UP
ã€ãã³ãã§çµäºãããã芪ViewGroupãå¶åŸ¡ãACTION_UP
ãããŸã§ãçŸåšã®ãžã§ã¹ãã£ã®ãã¹ãŠã®ã€ãã³ãããã®ãã¥ãŒã«åé¡ãããŸãïŒãã®åŸã ACTION_CANCELED
ã€ãã³ãã衚瀺ãããŸãïŒã ã€ãã³ãããã¥ãŒéå±€å
šäœãonTouchEvent(motionEvent: MotionEvent)
ãã誰ãé¢å¿ãæããªãã£ãå Žåã onTouchEvent(motionEvent: MotionEvent)
ã®ã¢ã¯ãã£ããã£onTouchEvent(motionEvent: MotionEvent)
ã«æ»ããŸãã

Androidã®ã£ã©ãªãŒã©ã€ãã©ãªã§ã¯ãæåã®ACTION_DOWN
ã€ãã³ããACTION_DOWN
dispatchTouchEvent()
ã«å°éããããã§motionEvent
trueãè¿ãonTouch()
å®è£
ã«æž¡ãããŸãã ããã«ããã¹ãŠã®ã€ãã³ãã¯ã次ã®ããããã«ãªããŸã§åããã§ãŒã³ãééããŸãã
ACTION_UP
;- ViewPagerã¯ãã¹ã¯ããŒã«ã®ããã«ã€ãã³ããã€ã³ã¿ãŒã»ããããããšããŸãã
- VerticalDragLayoutã¯ãã¹ã¯ã€ãããŠã€ãã³ããã€ã³ã¿ãŒã»ããããŠçµäºããããšããŸãã
onInterceptTouchEvent(motionEvent: MotionEvent)
ã¡ãœããã®onInterceptTouchEvent(motionEvent: MotionEvent)
ã®ã¿ãã€ãã³ããã€ã³ã¿ãŒã»ããã§ããŸãã ãã¥ãŒãMotionEventã«é¢å¿ãããå Žåã§ããã€ãã³ãèªäœã¯åã®ViewGroupãã§ãŒã³å
šäœã®dispatchTouchEvent(motionEvent: MotionEvent)
ééããŸãã ãããã£ãŠã芪ã¯åžžã«åäŸããèŠããã ãã¹ãŠã®èŠªViewGroupã¯ã€ãã³ããã€ã³ã¿ãŒã»ãããã onInterceptTouchEvent(motionEvent: MotionEvent)
ã§trueãè¿ãããšãã§ãããã¹ãŠã®åMotionEvent.ACTION_CANCEL
ã¯onTouchEvent(motionEvent: MotionEvent)
ã§onTouchEvent(motionEvent: MotionEvent)
ãåãåããŸãã
äŸïŒãŠãŒã¶ãŒãRecyclerViewã®èŠçŽ ã«æãåœãŠããšãåãèŠçŽ ã§ã€ãã³ããåŠçãããŸãã ããããæãäžäžã«åããå§ãããšããã«ãRecyclerViewã¯ã€ãã³ããã€ã³ã¿ãŒã»ããããã¹ã¯ããŒã«ãéå§ããããã¥ãŒã¯ACTION_CANCEL
ã€ãã³ããåãåããŸãã

Androidã®ã£ã©ãªãŒã§ãVerticalDragLayoutã¯ãã¹ã¯ã€ãã§ã€ãã³ããã€ã³ã¿ãŒã»ããããŠãViewPagerã§ã¹ã¯ããŒã«ã§ããŸãã ãã ããViewã¯requestDisallowInterceptTouchEvent(true)
ã¡ãœãããåŒã³åºãããšã«ããã芪ãã€ãã³ããrequestDisallowInterceptTouchEvent(true)
ããã®ãé²ãããšãã§ããŸãã ããã¯ããã¥ãŒããã®ãããªã¢ã¯ã·ã§ã³ãå®è¡ããå¿
èŠãããå Žåã«å¿
èŠã«ãªãå¯èœæ§ãããããã®ã€ã³ã¿ãŒã»ããã¯èŠªã«ãšã£ãŠæãŸãããããŸããã
ããšãã°ããã¬ãŒã€ãŒã®ãŠãŒã¶ãŒãç¹å®ã®æéãŸã§ãã©ãã¯ãã¹ãããããå Žåã 芪ViewPagerãæ°Žå¹³ã¹ã¯ããŒã«ãã€ã³ã¿ãŒã»ããããå Žåãæ¬¡ã®ãã©ãã¯ãžã®ç§»è¡ããããŸãã
ã¹ã¯ã€ããç¡èŠããŠåŠçããããã«ãVerticalDragLayoutãäœæããŸããããPhotoViewããã¿ããã€ãã³ããåãåããŸããã§ããã ãããèµ·ããçç±ãçè§£ããã«ã¯ãPhotoViewã§ã¿ããã€ãã³ããã©ã®ããã«åŠçãããããææ¡ããå¿
èŠããããŸããã
åŠçé åºïŒ
- VerticalDragLayoutã®MotionEvent.ACTION_DOWNã®å Žåã
interceptTouchEvent()
ããªã¬ãŒãããfalseãè¿ããŸãã ãã®ViewGroupã¯åçŽACTION_MOVEã®ã¿ã«é¢å¿ããããŸãã ACTION_MOVEæ¹åã¯dispatchTouchEvent()
ã§å®çŸ©ããããã®åŸãã€ãã³ãã¯super.dispatchTouchEvent()
ã¡ãœããã«æž¡ãããããã§ã€ãã³ãã¯VerticalDragLayoutã®interceptTouchEvent()
å®è£
ã«æž¡ãããŸãã

ACTION_DOWN
ã€ãã³ããonTouch()
ã¡ãœããã«å°éãããšããã¥ãŒã¯ã€ãã³ã管çãã€ã³ã¿ãŒã»ããããæ©èœã奪ããŸãã åŸç¶ã®ãã¹ãŠã®ãžã§ã¹ãã£ãŒã€ãã³ãã¯ã interceptTouchEvent()
ã¡ãœããã«åé¡ãããŸããã ã³ã³ãããŒã«ãã€ã³ã¿ãŒã»ããããæ©èœã¯ããžã§ã¹ãã£ãå®äºããå ŽåããŸãã¯ç»åã®å·Šå³ã®å¢çã§æ°Žå¹³æ¹åã®ACTION_MOVE
ããå Žåã«ã®ã¿èŠªã«äžããããŸãã
if (mAllowParentInterceptOnEdge && !mScaleDragDetector.isScaling() && !mBlockParentIntercept) { if (mScrollEdge == EDGE_BOTH || (mScrollEdge == EDGE_LEFT && dx >= 1f) || (mScrollEdge == EDGE_RIGHT && dx <= -1f)) { if (parent != null) { parent.requestDisallowInterceptTouchEvent(false); } } } else { if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } }

PhotoViewã§ã¯ãèŠªãæ°Žå¹³ã®ACTION_MOVE
å Žåã«ã®ã¿å¶åŸ¡ãååŸã§ããã¹ã¯ã€ãããŠéãããšåçŽã®ACTION_MOVE
ã§ãããããVerticalDragLayoutã¯ã€ãã³ãã³ã³ãããŒã«ãã€ã³ã¿ãŒã»ããããŠãžã§ã¹ãã£ãŒãå®è£
ã§ããŸããã ãããä¿®æ£ããã«ã¯ãåçŽã®ACTION_MOVE
å Žåã«å¶åŸ¡ãã€ã³ã¿ãŒã»ããããæ©èœã远å ããå¿
èŠããããŸãã
if (mAllowParentInterceptOnEdge && !mScaleDragDetector.isScaling() && !mBlockParentIntercept) { if (mHorizontalScrollEdge == HORIZONTAL_EDGE_BOTH || (mHorizontalScrollEdge == HORIZONTAL_EDGE_LEFT && dx >= 1f) || (mHorizontalScrollEdge == HORIZONTAL_EDGE_RIGHT && dx <= -1f) || mVerticalScrollEdge == VERTICAL_EDGE_BOTH || (mVerticalScrollEdge == VERTICAL_EDGE_TOP && dy >= 1f) || (mVerticalScrollEdge == VERTICAL_EDGE_BOTTOM && dy <= -1f)) { if (parent != null) { parent.requestDisallowInterceptTouchEvent(false); } } } else { if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } }
ããŠãæåã®åçŽã®å Žåã ACTION_MOVE
PhotoViewã¯èŠªãã€ã³ã¿ãŒã»ããããæ©äŒãäžããŸãïŒ

次ã®ACTION_MOVE
ã¯VerticalDragLyoutã§ã€ã³ã¿ãŒã»ããããã ACTION_CANCEL
ã€ãã³ãã¯åãã¥ãŒã«é£ã³ãŸãïŒ

ä»ã®ãã¹ãŠã®ACTION_MOVE
ã¯ãæšæºãã§ãŒã³ã«æ²¿ã£ãŠVerticalDragLayoutã«ç§»åããŸãã ViewGroupãåãã¥ãŒããã€ãã³ããå¶åŸ¡ããåŸãåãã¥ãŒãå¶åŸ¡ãåãæ»ããªãããšãéèŠã§ãã

ããã§ãPhotoViewã©ã€ãã©ãªã®ãµããŒããçµäºããããã«ã¹ã¯ã€ããå®è£
ããŸããã ã©ã€ãã©ãªã§ã¯ãPhotoViewã®å€æŽããããœãŒã¹ãå¥ã®ã¢ãžã¥ãŒã«ã§åãåºããŠäœ¿çšããå
ã®PhotoViewãªããžããªã«ããŒãžãªã¯ãšã¹ããäœæããŸããã
PhotoViewã«ãã€ã³ãè§£é€ãå®è£
ããŸã
ãããŠã³ã¹ãšã¯ãç»åããã®éçãè¶
ããŠã¹ã±ââãŒãªã³ã°ãããå Žåã®èš±å®¹å¯èœãªã¹ã±ãŒã«ã®ã¢ãã¡ãŒã·ã§ã³åŸ©å
ã§ããããšãæãåºããŠãã ããã

PhotoViewã§ã¯ãã®ãããªå¯èœæ§ã¯ãããŸããã§ããã ããããç§ãã¡ã¯ä»ã®èª°ãã®ãªãŒãã³ãœãŒã¹ãæãå§ããã®ã«ããªãããã§åæ¢ããã®ã§ãã PhotoViewã§ã¯ããºãŒã å¶éãèšå®ã§ããŸãã æåã¯ãããã¯æå°-x1ããã³æå€§-x3ã§ãã ç»åã¯ãããã®å¶éãè¶
ããããšã¯ã§ããŸããã
@Override public void onScale(float scaleFactor, float focusX, float focusY) { if ((getScale() < mMaxScale || scaleFactor < 1f) && (getScale() > mMinScale || scaleFactor > 1f)) { if (mScaleChangeListener != null) { mScaleChangeListener.onScaleChange(scaleFactor, focusX, focusY); } mSuppMatrix.postScale(scaleFactor, scaleFactor, focusX, focusY);
ã¯ããã«ããæå°å€ã«éãããšãã®ã¹ã±ãŒãªã³ã°ã®çŠæ¢ãæ¡ä»¶ãåé€ããããšã«ããŸãããåã«getScale() > mMinScale || scaleFactor > 1f
ãšããæ¡ä»¶ãgetScale() > mMinScale || scaleFactor > 1f
ããŸããã getScale() > mMinScale || scaleFactor > 1f
ã ãããŠãçªç¶...

ããã³ãç²åŸããŸããïŒ ã©ããããããã¯ã©ã€ãã©ãªã®äœæè
ãã©ã€ãã©ãªã2åå®å
šã«åçããããšã決å®ãããããŠã³ã¹ãšã¹ã±ãŒãªã³ã°ã®å¶éã®äž¡æ¹ãè¡ã£ãããã«çºçããããã§ãã onTouchã€ãã³ãã®å®è£
ãã€ãŸãMotionEvent.ACTION_UP
å ŽåããŠãŒã¶ãŒãæå€§/æå°ããã倧ãã/å°ããå Žåã AnimatedZoomRunnableãèµ·åãããç»åãå
ã®ãµã€ãºã«æ»ããŸãã
@Override public boolean onTouch(View v, MotionEvent ev) { boolean handled = false; switch (ev.getAction()) { case MotionEvent.ACTION_UP:
ã¹ã¯ã€ãã§éããã ãã§ãªããã©ã€ãã©ãªã®ãœãŒã¹ã§PhotoViewã確å®ããå
ã®PhotoViewã«ãããŠã³ã¹ãã远å ãããŠãã«ãªã¯ãšã¹ããäœæããŸããã
PhotoViewã®çªç¶ã®ãã°ãä¿®æ£
PhotoViewã«ã¯éåžžã«åä»ãªãã°ããããŸãã ãŠãŒã¶ãŒãããã«ã¿ããã§ç»åãæ¡å€§ãããå Žå 圌ã¯ãŠãããã®çºäœãèµ·ãããŠãã ç»åã®ã¹ã±ãŒãªã³ã°ãéå§ãããåçŽã«180床å転ã§ããŸãã ãã®ãã°ã¯ãCyanãªã©ã®Google Playã®äººæ°ã®ããã¢ããªã±ãŒã·ã§ã³ã§ãèŠã€ãããŸãã

é·ãæ€çŽ¢ã®åŸããã®ãã°ãããŒã«ã©ã€ãºããŸããïŒæã
ãè² ã®scaleFactorãã¹ã±ãŒãªã³ã°ã®ããã®ç»åã¹ã±ãŒãªã³ã°ã®ããã«å
¥åè¡åã«äžããããããã«ããç»åãå転ããŸãã
CustomGestureDetector
@Override public boolean onScale(ScaleGestureDetector detector) {
Android ScaleGestureDetectorããã¹ã±ãŒãªã³ã°ããã«ã¯ ãæ¬¡ã®ããã«èšç®ãããscaleFactor ãååŸããŸãã
public float getScaleFactor() { if (inAnchoredScaleMode()) {
ãããã°ãã°ã§ãã®ã¡ãœããããªãŒããŒã©ã€ããããšãè² ã®scaleFactorãååŸããã倿°ã®ç¹å®ã®å€ã远跡ã§ããŸãã
mEventBeforeOrAboveStartingGestureEvent is true; SCALE_FACTOR is 0.5; mCurrSpan: 1075.4398; mPrevSpan 38.867798; scaleUp: false; spanDiff: 13.334586; eval result is -12.334586
spanDiffã«SCALE_FACTOR == 0.5ãæããããšã«ããããã®åé¡ã解決ããããšããçãããããŸãã ããããmCurrSpanãšmPrevSpanã®éãã3å以äžã®å Žåããã®ãœãªã¥ãŒã·ã§ã³ã¯åœ¹ã«ç«ã¡ãŸããã ãã®ãã°ã®ãã±ããã¯ãã§ã«éå§ãããŠããŸããããŸã ä¿®æ£ãããŠããŸããã
æŸèæ ãã®åé¡ã®æãç°¡åãªè§£æ±ºçã¯ãè² ã®scaleFactorå€ãåçŽã«ã¹ãããããããšã§ãã å®éã«ã¯ããŠãŒã¶ãŒã¯ãç»åãéåžžããããããã«æ»ããã«ãºãŒã ãããªãããšããããŸãã
çµè«ã®ä»£ããã«
ãã«ãªã¯ãšã¹ãã®éåœ
ããŒã«ã«ã§ä¿®æ£ãè¡ããPhotoViewã§æåŸã®ãã«ãªã¯ãšã¹ããäœæããŸããã ããã€ãã®PRã1幎éãã³ã°ããŠãããšããäºå®ã«ãããããããPRãmasterãã©ã³ãã«è¿œå ãããPhotoViewã®æ°ãããªãªãŒã¹ã§ãããªãªãŒã¹ãããŸããã ãã®åŸãAndroidã®ã£ã©ãªãŒããããŒã«ã«ã¢ãžã¥ãŒã«ãåãåããå
¬åŒã®PhotoViewãœãŒã¹ãååŸããããšã«ããŸããã ãããè¡ãã«ã¯ãããŒãžã§ã³2.1.3ã§ PhotoViewã«è¿œå ãããAndroidXã®ãµããŒãã远å ããå¿
èŠããããŸããã
ã©ã€ãã©ãªã®å Žæ
ããã§Androidã®ã£ã©ãªãŒã©ã€ãã©ãªã®ãœãŒã¹ã³ãŒãïŒ https://github.com/redmadrobot-spb/android-gallery ïŒãäœ¿çšæé ãšãšãã«æ¢ããŸãã ãŸãããµããŒãã©ã€ãã©ãªãåŒãç¶ã䜿çšãããããžã§ã¯ãããµããŒãããããã«ã android-gallery-deprecatedã®å¥åã®ããŒãžã§ã³ãäœæããŸããã ãã ãããµããŒãã©ã€ãã©ãªã¯1幎ã§ã«ããã£ã«ãªãã®ã§æ³šæããŠãã ããïŒ
次ã¯äœã§ãã
ã©ã€ãã©ãªã¯å®å
šã«ç§ãã¡ã«åã£ãŠããŸãããéçºã®éçšã§æ°ããã¢ã€ãã¢ãçãŸããŸããã ãããã®ããã€ããæ¬¡ã«ç€ºããŸãã
- åå¥ã®FragmentDialogã ãã§ãªããä»»æã®ã¬ã€ã¢ãŠãã§ã©ã€ãã©ãªã䜿çšããæ©èœã
- UIãã«ã¹ã¿ãã€ãºããæ©èœã
- GildeãšExoPlayerã眮ãæããæ©èœã
- ViewPagerã®ä»£ããã«äœãã䜿çšããæ©èœã
åç
§è³æ
UPD
èšäºã®å·çäžã«ã FrescoImageViewerã®éçºè
ããã®åæ§ã®ã©ã€ãã©ãª ãç»å ŽããŸãã ã ãã©ã³ãžã·ã§ã³ã¢ãã¡ãŒã·ã§ã³ã®ãµããŒãã远å ãããŸãããããããŸã§ã®ãšãããããªã®ãµããŒããããããŸããã :)