Android中美丽的下划线
ÔÎÄÁ´½Ó : A better underline for Android
ÔÎÄ×÷Õß : Romain Guy
ÒëÎijö×Ô : ¾ò½ð·Òë¼Æ»®
ÒëÕß : jamweak
У¶ÔÕß: yifili09£¬whyalwaysmea
ÔÚ¹ýÈ¥Á½ÄêÀÎÒ¾³£·¢ÏÖһЩ³¢ÊÔÈ¥ÈçºÎÌá¸ßÓйØÔÚÍøÒ³ÖÐäÖȾÏ»®ÏßÎı¾ÐÞÊεÄÎÄÕºͿ⡣´ËÀàÎÊÌâҲͬÑù·¢ÉúÔÚAndroid£¨Æ½Ì¨£©£ºÏ»®ÏßµÄÎı¾ÐÞÊÎÓë½µ²¿Ïཻ¡£±È½ÏÏÂAndroidµ±Ç°ÈçºÎ»æÖÆÏ»®ÏßÎı¾(ÉÏͼ)ÒÔ¼°ËüµÄÌæ´ú·½°¸(ÏÂͼ)£º
Äã¸üϲ»¶ÄÄÒ»ÖÖ?
¾¡¹ÜÎÒÍêÈ«ÈÏ¿ÉÕâЩŬÁ¦£¬µ«ÊÇÎÒ´Óδϲ»¶¹ýÈκι«¿ªµÄ½â¾ö·½·¨¡£Ä¿Ç°×îеļ¼Êõ£¨×·ÇóÒÕÊõ°ãµÄ״̬£©¡ªºÁÎÞÒÉÎʵػáÇ¿ÆÈ¿ª·¢ÕßÃÇÊÜÏÞÓÚCSS¡ªËƺõÊÇͨ¹ý»æÖÆÏßÐÔ½¥±äÒÔ¼°¶àÖØÒõÓ°£¨ÎÒ¼û¹ý¶à´ï12²ãµÄ£¡£©À´ÊµÏֵġ£ÕâЩ½â¾ö·½°¸¶¼¾ßÓÐÎÞ·¨·ñÈϵijÉЧ£¬µ«ÕâÖÖ»æÖÆÈç´Ë¶àÒõÓ°µÄ×ö·¨£¬¼´Ê¹Ã»ÓÐÔö¼ÓÄ£ºýЧ¹û£¬Ò²»áʹµÃͼÐοª·¢ÕßÃÇ×㹻ͷÌÛÁË¡£»¹ÓÐÒ»µã£¬ÕâÖÖ·½·¨½ö½öÔÚʵɫµÄ±³¾°ÏÂÓÐЧ¡£
ÎÒ½ñÌìÏÂÎçһʱÐËÆ𣬿ªÊ¼×ÅÊÖ·¢¾òÂú×ãÒÔÏÂÐèÇóµÄÆäËû½â¾ö·½°¸:
-
¼æÈݾɰ汾µÄAndroidϵͳ
-
½öʹÓñê×¼µÄViewºÍCanvas APIs
-
²»ÐèÒª¹ý¶ÈÖØ»æ»òÕß´óÁ¿µÄÒõÓ°¿ªÏú
-
ÔÚÈκα³¾°Ï¶¼ÓÐЧ£¬¶ø²»ÊÇÖ»Ö§³Öʵɫ±³¾°
-
²»ÒÀÀµ»æÖÆÁ÷Ë®ÏߵIJÙ×÷˳Ðò(Îı¾ÏÈÓÚ/ÍíÓÚÏ»®ÏߵĻæÖÆÊÇÎ޹ؽôÒªµÄ)
ÎÒÔÚÕâÀïÌṩÁËÁ½ÖÖ½â¾ö·½°¸£¬Äã¿ÉÒÔÔÚGitHub»ñÈ¡¡£ÆäÖÐÒ»ÖÖ·½·¨ÊÊÓÃÓÚAPI level 19¼°ÒÔÉÏ£¬ÁíÍâÒ»ÖÖÊÊÓÃÓÚAPI level 1¼°ÒÔÉÏ£¬»òÕß˵Ëü Ó¦¸Ã ÖÁÉÙÖ§³ÖAPI level 1ÒÔÉÏ£¬ÎÒûÓÐÍêÈ«µØ²âÊÔ£¬µ«ÎÒÏàÐÅAPIÎĵµ¡£
Äã¿ÉÒÔÔÚÏÂÃæµÄ½ØͼÖй۲ì±È½ÏÏÂÕâÁ½ÖÖ±»³Æ×÷ Path ºÍ Region µÄ·½·¨£º
ÔÚAndroidÖиüºÃչʾÏ»®ÏßÎı¾µÄÁ½ÖÖ¿ÉÄܵÄʵÏÖ·½Ê½
ÈçºÎʵÏÖµÄ?
ÕâЩʵÏÖ±³ºóµÄ˼ÏëÓë֮ǰÌáµ½µÄCSS·½·¨³öÆæµØÀàËÆ¡£ÎÒÃÇʹÓÃÒ»ÕûÌõÖ±Ï߶ÎÀ´±íʾÏ»®Ïߣ¬Ê£ÏÂËùÐèÒª×öµÄ¾ÍÊÇΪ½µ²¿Å²³ö¿Õ¼ä...
ʹÓÃPathÀà
API level 19 (½ÐKitKat¸ü¶úÊì) ÖÐÒýÈëÁËÒ»¸ö²Ù×÷·¾¶µÄÐÂAPI½Ð×öpath ops¡£Õâ¸öAPIÔÊÐíÄãΪʵÀý½¨Á¢Á½¸ö·¾¶µÄ½»²æµã£¬»òÊÇ´ÓÒ»Ìõ·¾¶ÖмõÈ¥ÆäËüµÄ·¾¶¡£
ʹÓÃÕâ¸öAPI£¬ÖÆ×÷ÎÒÃÇÏëÒªµÄÏ»®Ï߾ͷdz£¼òµ¥ÁË¡£µÚÒ»²½¾ÍÊÇΪÎÒÃǵÄÎı¾»ñÈ¡ÂÖÀª£º
mPaint.getTextPath(mText, 0, mText.length(), 0.0f, 0.0f, mOutline);
×¢Òâ·µ»ØµÄpath¿ÉÒÔͨ¹ýÒ»ÖÖÌî³äµÄÑùʽÀ´äÖȾÔʼÎı¾£¬ÎÒÃÇÔÚÕâÀïҪʹÓÃËüÀ´½øÐкóÐø²Ù×÷¡£
Îı¾ÂÖÀª
ÏÂÒ»²½¾ÍÊǼôÇбíʾÏ»®ÏߵľØÐÎÂÖÀª¡£ÕâÒ»²½²»ÍêÈ«ÊDZØÒªµÄ£¬µ«ÊÇÕâÑù¿ÉÒÔ±ÜÃâÔÚÏÂÒ»²½¿ÉÄܳöÏֵĽüËÆֵƫ²î¡£ÎÒÃÇÖ»ÐèʹÓÃintersection path²Ù×÷¾ÍÄÜ·½±ãµÄʵÏÖÕâÒ»¹¦ÄÜ£º
mOutline.op(mUnderline, Path.Op.INTERSECT);
ÏÖÔÚÂÖÀªÂ·¾¶½ö½ö°üº¬¼¸Î»½µ²¿ÓëÏ»®ÏߵĽ»²æ²¿·Ö¡£
Ö»ÓкÚÉ«ÇøÓò±íʾÊÇ·¾¶µÄÒ»²¿·Ö£¬ÆäÓàµÄ²¿·ÖÖ»ÊÇΪÁË¿ÉÊÓÄ¿µÄ¡£
Ê£ÏÂÒª×öµÄ¾ÍÊÇ´ÓÏ»®ÏßÖмõÈ¥ÄÇЩ½µ²¿Î»ÖõIJ¿·Ö¡£ÔÚ×öÕâ¸ö֮ǰ£¬ÎÒÃDZØÐëÀ©´óÔʼÎı¾µÄ³ß´çÀ´Îª½µ²¿ÓëÏ»®Ï߼䴴Ôì³ö¼ä϶¡£Õâ¸ö¹¦ÄÜ¿ÉÒÔͨ¹ý»®³ýÎÒÃǼôÇеÄÂÖÀªÈ»ºó½¨Á¢Ò»¸öеÄÌî³ä·¾¶ÊµÏÖ£º
mStroke.setStyle(Paint.Style.FILL_AND_STROKE);
mStroke.setStrokeWidth(UNDERLINE_CLEAR_GAP);
mStroke.getFillPath(mOutline, strokedOutline);
»®µôµÄ¿í´ø´ú±í×ÅÄãÏëΪ½µ²¿ºÍÏ»®ÏßÖ®¼äÁô϶à´óµÄ¿Õ¼ä¡£
»®³ý¼ôÇеôµÄÂÖÀª
×îºóÒ»²½¾ÍÊÇʹÓÃÁíÍâÒ»¸öpath²Ù×÷´ÓÏ»®Ïß¾ØÐÎÂÖÀªÖмõÈ¥»®³ý²¿·ÖºÍ¼ôÇеôµÄ²¿·Ö£º
mUnderline.op(strokedOutline, Path.Op.DIFFERENCE);
×îºóµÄÏ»®Ïß¿ÉÒÔʹÓÃÒ»¸öÌî³ä»±Ê»æÖÆ£º
canvas.drawPath(mUnderline, mPaint);
ʹÓÃRegionÀà
RegionÊÇÒ»ÖÖÔÚÆÁÄ»ÉϸßЧչʾ·Ç¾ØÐÎÐÎ×´µÄ·½·¨¡£Äã¿ÉÒÔÏëÏóÒ»¿éÇøÓòÊÇÓÉÈô¸É¶ÔÆëµ½äÖȾ»º³åÇøµÄ¾ØÐμ¯ºÏ×é³ÉµÄ¡£Regions¿ÉÒÔ±»¿´×÷ÊÇÕ¤¸ñ»¯µÄPath¡£ÕâÒâζ×ÅÈç¹ûÎÒÃǽ«Pathת»»³ÉRegionºó£¬ÎÒÃÇ»ñµÃµÄÊÇһϵÁÐÏñËØ×ø±êµãµÄ¼¯ºÏ£¬Ò»µ©Path±»»æÖÆ£¬Ëü½«Ó°Ïìµ½ÕâЩ»ñµÃµÄ×ø±ê¼¯ºÏ¡£
RegionÓÐȤµÄµØ·½ÔÚÓÚËüÌṩÁËÓëPathÏàͬµÄ²Ù×÷¡£Á½¿éRegionsÄܹ»»¥Ïཻ´í¡¢¿Û³ýÖصþµÄ²¿·ÖµÈµÈ¡£¸üÖØÒªµÄÊÇ£¬Region´Ó×îÔçµÄAndroid APIÖоÍÒѾ´æÔÚÁË¡£
ÓÃRegionʵÏÖÏ»®Ïߵķ½·¨¼¸ºõÓëÓÃPathÍêÈ«Ïàͬ£¬Ö÷ÒªµÄÇø±ð´æÔÚÓÚÂÖÀªºÎʱÔõÑù±»¼ôÇеģº
Region underlineRegion = new Region(underlineRect);
// ΪÎı¾½¨Á¢Ò»¸öRegion²¢ÇÒ¼ôÇеôÏ»®Ïß²¿·Ö
Region outlineRegion = new Region();
outlineRegion.setPath(mOutline, underlineRegion);
// ÌáÈ¡·µ»ØµÄRegionµÄPath£¬´Ó¶ø»ñµÃÒ»·Ý¼ôÇкóµÄÎı¾ÂÖÀªµÄ¿½±´
mOutline.rewind();
outlineRegion.getBoundaryPath(mOutline);
// »®µô¼ôÇеôµÄÎı¾£¬½«Æä½á¹ûתΪһ¸öÌî³äÑùʽµÄPath
mStroke.getFillPath(mOutline, strokedOutline);
// ʹÓû®µôÎı¾µÄÂÖÀª½¨Á¢Ò»¸öRegion¶ÔÏó
outlineRegion = new Region();
outlineRegion.setPath(strokedOutline, new Region(mBounds));
// ÔÚÏ»®ÏßÂÖÀªÖп۳ý¼ôÇеôµÄ£¬»®µôµÄÎı¾ÂÖÀª
underlineRegion.op(outlineRegion, Region.Op.DIFFERENCE);
// ʹÓÃÏ»®ÏßRegion½¨Á¢Ò»¸öPath
underlineRegion.getBoundaryPath(mUnderline);
Á½ÖÖ·½·¨µÄÇø±ð
ÓÉÓÚPathÀàºÍRegionÀàµÄ±¾Öʲ»Í¬£¬Á½ÖÖʵÏÖ¼äÓÐ×Ų»Òײì¾õµÄÇø±ð¡£ÒòΪPathÀà½ö½öÔÚÇúÏßÉϲÙ×÷£¬Òò´ËÔÚÎÒÃÇ´ÓÏ»®ÏßÂÖÀªÖп۳ý½µ²¿Ê±£¬¾Í±£ÁôÁ˽µ²¿ÂÖÀªµÄб¶È£¬Õâ¾ÍÔì³ÉÏ»®Ïß¿Õ϶µÄ±ßÔµÓë½µ²¿µÄÇúÏßб¶ÈƽÐС£ÕâÖÖЧ¹û»òÐíÊÇÓÖ»òÐí²»ÊÇËùÆÚÍûµÄ¡£
ÁíÒ»·½Ã棬RegionÀà²Ù×÷µÄÊÇÕû¸öÏñËص㣬Ëü»áÇå³ýÏ»®ÏßÊúÏòµÄÇиÄãµÄÏ»®Ïß×㹻ϸµÄ»°£©¡£ÏÂͼÊÇÁ½ÖÖʵÏֵıȽϣº
ÉÏͼ: PathÀà. ÏÂͼ: RegionÀà. ×¢Òâµ½ÉÏÃæµÄб¶Èû£¿Èç¹ûûÓÐ,ÄãÐèÒª×Ðϸ¿´¡£
Ó¦µ±ÔÚ²úÆ·ÖÐʹÓÃÂð?
ÔÚÄã³¢ÊÔ½«ÕâЩ¼¼ÊõÔËÓõ½ÄãµÄÓ¦ÓÃ֮ǰ£¬ÐèÒªÁ˽⵽ÎÒÕâ´ÎûÓÐ×öÈκεÄÐÔÄܲâÊÔ¡£Çë¼ÇסÕâЩ³¢ÊԺܴó³Ì¶ÈÉÏÖ»ÊÇÒ»ÖÖ±à³ÌÀÖȤµÄÌôÕ½¡£ËùÌṩµÄ´úÂëûÓиù¾ÝÎı¾µÄ´óСÀ´ÊÊÅäÏ»®ÏßµÄλÖã¬Ò²Ã»ÓÐÊÊÅä¼ä϶µÄ¿í¶È¡£¿ÉÄÜÔÚ×ÖÌåµÄÊÊÅäÉÏÒ²ÓÐÎÊÌ⣬ÎÒÖ»³¢ÊÔÁ˼¸ÖÖAndroidĬÈϵÄ×ÖÐÍ¡£¾ÍÈÃÎÒÃǽ«ÕâЩÎÊÌâÁô¸ø¶ÁÕßµ±×öÁ·Ï°À´½â¾ö°É¡£
Èç¹ûÄ㽫³¢ÊÔ×ÅÔÚÄãµÄÓ¦ÓÃÀïʹÓÃÕâЩ´úÂ룬ÄÇôÎÒ±ØÐë³ÐÈÏÎÒ½«ºÜÀÖÓÚ¿´µ½¹ØÓÚspansµÄʵÏÖ£¬ÎÒ»á¹ÄÀøÄãÖÁÉÙ»º´æÒ»ÏÂ×îºóµÄÌî³äPath¡£ÓÉÓÚËü½ö½öÒÀÀµÓÚ×ÖÐÍ£¬×ÖÌåºÍ×Ö·û´®£¬»º´æ»¹ÊDZȽÏÈÝÒ×ʵÏֵġ£
ÁíÍ⣬ÎÄÕÂÖÐÃèÊöµÄÕâÁ½ÖÖʵÏÖ·½·¨ÍêÈ«Ñϸñ×ñÑ¿ª·ÅµÄSDK API¡£Èç¹ûÔÚAndroid framework²ãÖ±½ÓʵÏֵĻ°£¬ÎÒÓÐһЩÏë·¨ÄÜʹµÃÕâ¸ö¹¦ÄܱäµÃ¸üÓÐЧÂÊ¡£
±ÈÈç Region µÄת»»Äܹ»Í¨¹ýäÖȾ×ÔÉíÀ´»ñµÃÓÅ»¯£¬¶ø²»ÓÃת»»»Ø Path ÁË£¨Õâ»áÔì³ÉÈí¼þµÄËéƬ»¯ÒÔ¼°GPU½á¹¹»¯¸üУ©¡£RegionÀà±¾Éí¾ÍÊÇһϵÁоØÐεļ¯ºÏ£¬¶ÔÓÚäÖȾÁ÷Ë®ÏßÀ´Ëµ£¬Óë»æÖÆËéƬ»¯µÄPathÏà±È£¬»æÖÆһϵÁеÄÖ±Ïß»ò¾ØÐαäµÃÈÝÒ׶àÁË¡£
ÄãÏëÁ˽â¸ü¶à¹ØÓÚAndroidÎı¾µÄ¶«Î÷£¿Ñ§Ï°AndroidµÄÓ²¼þÊÇÈçºÎ¼ÓËÙ×ÖÌåäÖȾµÄ£¿¡£
ÔÚGitHubÉÏ»ñÈ¡ÑÝʾԴÂë¡£