Android中美丽的下划线

ÔÚ¹ýÈ¥Á½ÄêÀÎÒ¾­³£·¢ÏÖһЩ³¢ÊÔÈ¥ÈçºÎÌá¸ßÓйØÔÚÍøÒ³ÖÐäÖȾÏ»®ÏßÎı¾ÐÞÊεÄÎÄÕºͿ⡣´ËÀàÎÊÌâҲͬÑù·¢ÉúÔÚAndroid£¨Æ½Ì¨£©£ºÏ»®ÏßµÄÎı¾ÐÞÊÎÓë½µ²¿Ïཻ¡£±È½ÏÏÂAndroidµ±Ç°ÈçºÎ»æÖÆÏ»®ÏßÎı¾(ÉÏͼ)ÒÔ¼°ËüµÄÌæ´ú·½°¸(ÏÂͼ)£º

687474703a2f2f7777332e73696e61696d672e636e2f6c617267652f613439303134376667773166356a327867637a69726a323064353036716d78672e6a7067.jpeg

Äã¸üϲ»¶ÄÄÒ»ÖÖ?

¾¡¹ÜÎÒÍêÈ«ÈÏ¿ÉÕâЩŬÁ¦£¬µ«ÊÇÎÒ´Óδϲ»¶¹ýÈκι«¿ªµÄ½â¾ö·½·¨¡£Ä¿Ç°×îеļ¼Êõ£¨×·ÇóÒÕÊõ°ãµÄ״̬£©¡ªºÁÎÞÒÉÎʵػáÇ¿ÆÈ¿ª·¢ÕßÃÇÊÜÏÞÓÚCSS¡ªËƺõÊÇͨ¹ý»æÖÆÏßÐÔ½¥±äÒÔ¼°¶àÖØÒõÓ°£¨ÎÒ¼û¹ý¶à´ï12²ãµÄ£¡£©À´ÊµÏֵġ£ÕâЩ½â¾ö·½°¸¶¼¾ßÓÐÎÞ·¨·ñÈϵijÉЧ£¬µ«ÕâÖÖ»æÖÆÈç´Ë¶àÒõÓ°µÄ×ö·¨£¬¼´Ê¹Ã»ÓÐÔö¼ÓÄ£ºýЧ¹û£¬Ò²»áʹµÃͼÐοª·¢ÕßÃÇ×㹻ͷÌÛÁË¡£»¹ÓÐÒ»µã£¬ÕâÖÖ·½·¨½ö½öÔÚʵɫµÄ±³¾°ÏÂÓÐЧ¡£

ÎÒ½ñÌìÏÂÎçһʱÐËÆ𣬿ªÊ¼×ÅÊÖ·¢¾òÂú×ãÒÔÏÂÐèÇóµÄÆäËû½â¾ö·½°¸:

  • ¼æÈݾɰ汾µÄAndroidϵͳ

  • ½öʹÓñê×¼µÄViewºÍCanvas APIs

  • ²»ÐèÒª¹ý¶ÈÖØ»æ»òÕß´óÁ¿µÄÒõÓ°¿ªÏú

  • ÔÚÈκα³¾°Ï¶¼ÓÐЧ£¬¶ø²»ÊÇÖ»Ö§³Öʵɫ±³¾°

  • ²»ÒÀÀµ»æÖÆÁ÷Ë®ÏߵIJÙ×÷˳Ðò(Îı¾ÏÈÓÚ/ÍíÓÚÏ»®ÏߵĻæÖÆÊÇÎ޹ؽôÒªµÄ)

ÎÒÔÚÕâÀïÌṩÁËÁ½ÖÖ½â¾ö·½°¸£¬Äã¿ÉÒÔÔÚGitHub»ñÈ¡¡£ÆäÖÐÒ»ÖÖ·½·¨ÊÊÓÃÓÚAPI level 19¼°ÒÔÉÏ£¬ÁíÍâÒ»ÖÖÊÊÓÃÓÚAPI level 1¼°ÒÔÉÏ£¬»òÕß˵Ëü Ó¦¸Ã ÖÁÉÙÖ§³ÖAPI level 1ÒÔÉÏ£¬ÎÒûÓÐÍêÈ«µØ²âÊÔ£¬µ«ÎÒÏàÐÅAPIÎĵµ¡£

Äã¿ÉÒÔÔÚÏÂÃæµÄ½ØͼÖй۲ì±È½ÏÏÂÕâÁ½ÖÖ±»³Æ×÷ Path ºÍ Region µÄ·½·¨£º

687474703a2f2f7777332e73696e61696d672e636e2f6c617267652f613439303134376667773166356a3279356138386e6a32306a3130787a3076762e6a7067.jpeg

ÔÚ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¿ÉÒÔͨ¹ýÒ»ÖÖÌî³äµÄÑùʽÀ´äÖȾԭʼÎı¾£¬ÎÒÃÇÔÚÕâÀïҪʹÓÃËüÀ´½øÐкóÐø²Ù×÷¡£

687474703a2f2f7777312e73696e61696d672e636e2f6c617267652f613439303134376667773166356a327a36626169676a32306d3830353761616a2e6a7067.jpeg

Îı¾ÂÖÀª

ÏÂÒ»²½¾ÍÊǼôÇбíʾÏ»®ÏߵľØÐÎÂÖÀª¡£ÕâÒ»²½²»ÍêÈ«ÊDZØÒªµÄ£¬µ«ÊÇÕâÑù¿ÉÒÔ±ÜÃâÔÚÏÂÒ»²½¿ÉÄܳöÏֵĽüËÆֵƫ²î¡£ÎÒÃÇÖ»ÐèʹÓÃintersection path²Ù×÷¾ÍÄÜ·½±ãµÄʵÏÖÕâÒ»¹¦ÄÜ£º

mOutline.op(mUnderline, Path.Op.INTERSECT);

ÏÖÔÚÂÖÀªÂ·¾¶½ö½ö°üº¬¼¸Î»½µ²¿ÓëÏ»®ÏߵĽ»²æ²¿·Ö¡£

687474703a2f2f7777312e73696e61696d672e636e2f6c617267652f613439303134376667773166356a327a6f723270746a32306d3830346c7765742e6a7067.jpeg

Ö»ÓкÚÉ«ÇøÓò±íʾÊÇ·¾¶µÄÒ»²¿·Ö£¬ÆäÓàµÄ²¿·ÖÖ»ÊÇΪÁË¿ÉÊÓÄ¿µÄ¡£

Ê£ÏÂÒª×öµÄ¾ÍÊÇ´ÓÏ»®ÏßÖмõÈ¥ÄÇЩ½µ²¿Î»ÖõIJ¿·Ö¡£ÔÚ×öÕâ¸ö֮ǰ£¬ÎÒÃDZØÐëÀ©´óԭʼÎı¾µÄ³ß´çÀ´Îª½µ²¿ÓëÏ»®Ï߼䴴Ôì³ö¼ä϶¡£Õâ¸ö¹¦ÄÜ¿ÉÒÔͨ¹ý»®³ýÎÒÃǼôÇеÄÂÖÀªÈ»ºó½¨Á¢Ò»¸öеÄÌî³ä·¾¶ÊµÏÖ£º

mStroke.setStyle(Paint.Style.FILL_AND_STROKE);        
mStroke.setStrokeWidth(UNDERLINE_CLEAR_GAP);
mStroke.getFillPath(mOutline, strokedOutline);

»®µôµÄ¿í´ø´ú±í×ÅÄãÏëΪ½µ²¿ºÍÏ»®ÏßÖ®¼äÁô϶à´óµÄ¿Õ¼ä¡£

687474703a2f2f7777322e73696e61696d672e636e2f6c617267652f613439303134376667773166356a333037367a75766a32306d383034677133612e6a7067.jpeg

»®³ý¼ôÇеôµÄÂÖÀª

×îºóÒ»²½¾ÍÊÇʹÓÃÁíÍâÒ»¸ö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Àà²Ù×÷µÄÊÇÕû¸öÏñËص㣬Ëü»áÇå³ýÏ»®ÏßÊúÏòµÄÇиÄãµÄÏ»®Ïß×㹻ϸµÄ»°£©¡£ÏÂͼÊÇÁ½ÖÖʵÏֵıȽϣº

687474703a2f2f7777342e73696e61696d672e636e2f6c617267652f613439303134376667773166356a333135723976656a3230363730626d3073782e6a7067.jpeg

ÉÏͼ: PathÀà. ÏÂͼ: RegionÀà. ×¢Òâµ½ÉÏÃæµÄб¶Èû£¿Èç¹ûûÓÐ,ÄãÐèÒª×Ðϸ¿´¡£

Ó¦µ±ÔÚ²úÆ·ÖÐʹÓÃÂð?

ÔÚÄã³¢ÊÔ½«ÕâЩ¼¼ÊõÔËÓõ½ÄãµÄÓ¦ÓÃ֮ǰ£¬ÐèÒªÁ˽⵽ÎÒÕâ´ÎûÓÐ×öÈκεÄÐÔÄܲâÊÔ¡£Çë¼ÇסÕâЩ³¢ÊԺܴó³Ì¶ÈÉÏÖ»ÊÇÒ»ÖÖ±à³ÌÀÖȤµÄÌôÕ½¡£ËùÌṩµÄ´úÂëûÓиù¾ÝÎı¾µÄ´óСÀ´ÊÊÅäÏ»®ÏßµÄλÖã¬Ò²Ã»ÓÐÊÊÅä¼ä϶µÄ¿í¶È¡£¿ÉÄÜÔÚ×ÖÌåµÄÊÊÅäÉÏÒ²ÓÐÎÊÌ⣬ÎÒÖ»³¢ÊÔÁ˼¸ÖÖAndroidĬÈϵÄ×ÖÐÍ¡£¾ÍÈÃÎÒÃǽ«ÕâЩÎÊÌâÁô¸ø¶ÁÕßµ±×öÁ·Ï°À´½â¾ö°É¡£

Èç¹ûÄ㽫³¢ÊÔ×ÅÔÚÄãµÄÓ¦ÓÃÀïʹÓÃÕâЩ´úÂ룬ÄÇôÎÒ±ØÐë³ÐÈÏÎÒ½«ºÜÀÖÓÚ¿´µ½¹ØÓÚspansµÄʵÏÖ£¬ÎÒ»á¹ÄÀøÄãÖÁÉÙ»º´æÒ»ÏÂ×îºóµÄÌî³äPath¡£ÓÉÓÚËü½ö½öÒÀÀµÓÚ×ÖÐÍ£¬×ÖÌåºÍ×Ö·û´®£¬»º´æ»¹ÊDZȽÏÈÝÒ×ʵÏֵġ£

ÁíÍ⣬ÎÄÕÂÖÐÃèÊöµÄÕâÁ½ÖÖʵÏÖ·½·¨ÍêÈ«Ñϸñ×ñÑ­¿ª·ÅµÄSDK API¡£Èç¹ûÔÚAndroid framework²ãÖ±½ÓʵÏֵĻ°£¬ÎÒÓÐһЩÏë·¨ÄÜʹµÃÕâ¸ö¹¦ÄܱäµÃ¸üÓÐЧÂÊ¡£

±ÈÈç Region µÄת»»Äܹ»Í¨¹ýäÖȾ×ÔÉíÀ´»ñµÃÓÅ»¯£¬¶ø²»ÓÃת»»»Ø Path ÁË£¨Õâ»áÔì³ÉÈí¼þµÄËéƬ»¯ÒÔ¼°GPU½á¹¹»¯¸üУ©¡£RegionÀà±¾Éí¾ÍÊÇһϵÁоØÐεļ¯ºÏ£¬¶ÔÓÚäÖȾÁ÷Ë®ÏßÀ´Ëµ£¬Óë»æÖÆËéƬ»¯µÄPathÏà±È£¬»æÖÆһϵÁеÄÖ±Ïß»ò¾ØÐαäµÃÈÝÒ׶àÁË¡£

ÄãÏëÁ˽â¸ü¶à¹ØÓÚAndroidÎı¾µÄ¶«Î÷£¿Ñ§Ï°AndroidµÄÓ²¼þÊÇÈçºÎ¼ÓËÙ×ÖÌåäÖȾµÄ£¿¡£

ÔÚGitHubÉÏ»ñÈ¡ÑÝʾԴÂë¡£