1. Overview
Learn Android can not but imitate a variety of app interface, since the micro-letter 6.0 After the advent of the micro-letter switch when the color of the tab icon?? Ken Hu Yi Pain? ㄒ Jian and??? Indistinct Shenyang Lai Meshan?
OK, let's look at the effect chart:
Clarity is not very good, we do see ~ ~ There are wood feel this weak burst of color,,, I move my fingers to change your color:
There is no this color comparison demon a little ~ ~ ~ Well ~ below begins to introduce the principle.
2. Principle Introduction
Through the above effect chart, you may also guess, our icon is not two pictures, but a picture, and the target color is customizable, who let now talk about personalization.
So how do we do that, you can make the icon in the heart of the color of the encounter, below you will see a familiar picture:
There is no very familiar sense of foot, we actually still use the paint xfermode, this time we are using: mode.dst_in
Dst_in Review what effect, first to draw DST, set mode, and then draw SRC, it shows the intersection area of the plot, and is DST.
Take a closer look at our icons:
In order to facilitate the viewing, I purposely took PS selected the opacity of our icon, we can see that our small robot non-transparent area is the part of the wire frame.
Then, the principle of changing the color of our icons appears:
1, first draw a color (for example: pink)
2, set mode=dst_in
3. Draw us this cute little robot
Answer me, show what, is not show intersection, what is the intersection? The intersection is the non-transparent area of our little robot, which is the face, except for two eyes;
Okay, so how does it change color?
When I draw a color, can't I set alpha?
To this, we should already understand the principle of the drawing of our icons.
3, Custom icon control
Our entire interface Needless to say, is viewpager+fragment, is now concerned about the bottom ~ ~
Next we consider that the bottom of the Tab,tab our layout is linearlayout, the interior four view, through the set weight to achieve the average ~ ~
This view is our custom icon control, which we call: Changecoloriconwithtextview
Next consider what attributes should be posted out
1, custom properties
For a moment, I decided to put the icon, icon color, the text displayed under the icon, the text size of these four properties as custom attributes.
Then the custom attribute goes up:
A, Values/attr.xml
The code is as follows |
Copy Code |
<?xml version= "1.0" encoding= "Utf-8"?> <resources>
<attr name= "icon" format= "Reference"/> <attr name= "Color" format= "Color"/> <attr name= "Text" format= "string"/> <attr name= "Text_size" format= "Dimension"/>
<declare-styleable name= "Changecoloriconview" > <attr name= "icon"/> <attr name= "Color"/> <attr name= "Text"/> <attr name= "Text_size"/> </declare-styleable>
</resources> |
b, using in Layout files
code is as follows |
copy code |
<com.zhy.weixin6.ui.changecoloriconwithtextview android:id= "@+id/id_indicator_one" android:layout_width= "0DP" android: layout_height= "Fill_parent" android: layout_weight= "1" android:padding= "5DP" zhy:icon= "@drawable/ic_menu_start_ Conversation " zhy:text=" @string/tab_ Weixin " zhy:text_size=" 12SP "/> |
Pay attention to the namespace of the writing, xmlns:zhy= "http://schemas.android.com/apk/res/application of the package name."
C, in the construction method to obtain
The code is as follows |
Copy Code |
public class Changecoloriconwithtextview extends View
{
Private Bitmap Mbitmap;
Private Canvas Mcanvas;
Private Paint Mpaint;
/**
* Color
*/
private int mcolor = 0xff45c01a;
/**
* Transparency 0.0-1.0
*/
private float Malpha = 0f;
/**
* Icon
*/
Private Bitmap Miconbitmap;
/**
* Limit the scope of the drawing icon
*/
Private Rect Miconrect;
/**
* Icon Bottom Text
*/
Private String Mtext = "micro-letter";
private int mtextsize = (int) typedvalue.applydimension (
TYPEDVALUE.COMPLEX_UNIT_SP, Getresources (). Getdisplaymetrics ());
Private Paint Mtextpaint;
Private Rect Mtextbound = new Rect ();
Public Changecoloriconwithtextview
{
Super (context);
}
/**
* Initialize the custom attribute value
*
* @param context
* @param attrs
*/
Public Changecoloriconwithtextview (context, AttributeSet attrs)
{
Super (context, attrs);
Gets the icon for the setting
TypedArray a = Context.obtainstyledattributes (Attrs,
R.styleable.changecoloriconview);
int n = a.getindexcount ();
for (int i = 0; i < n; i++)
{
int attr = A.getindex (i);
Switch (attr)
{
Case R.styleable.changecoloriconview_icon:
Bitmapdrawable drawable = (bitmapdrawable) a.getdrawable (attr);
Miconbitmap = Drawable.getbitmap ();
Break
Case R.styleable.changecoloriconview_color:
Mcolor = A.getcolor (attr, 0x45c01a);
Break
Case R.styleable.changecoloriconview_text:
Mtext = a.getstring (attr);
Break
Case R.styleable.changecoloriconview_text_size:
mtextsize = (int) a.getdimension (attr, Typedvalue
. Applydimension (TYPEDVALUE.COMPLEX_UNIT_SP, 10,
Getresources (). Getdisplaymetrics ());
Break
}
}
A.recycle ();
Mtextpaint = new Paint ();
Mtextpaint.settextsize (mtextsize);
Mtextpaint.setcolor (0xff555555);
Get text Draw Range
Mtextpaint.gettextbounds (mtext, 0, Mtext.length (), mtextbound);
}
|
As you can see, we get the custom attributes in the constructor, and the controls that have the text occupy are in our mtextbound.
2, the selection of the drawing area of the icon
We consider that, with attributes, we need to draw a text, an icon above the text, how do we control the area of the plot?
Our view display area is in the following three situations:
In view of these three kinds of situation, what should be the side length of the icon of my door?
I think the side length should be: the height of the control-the height of the text-the small value of the inner margin and the width of the control-the inner margin; let's examine it carefully;
Well, with the above side-length conclusion, we begin to compute the scope of the icon:
The code is as follows |
Copy Code |
@Override
protected void onmeasure (int widthmeasurespec, int heightmeasurespec)
{
Super.onmeasure (Widthmeasurespec, Heightmeasurespec);
Get the width of the drawing icon
int bitmapwidth = Math.min (Getmeasuredwidth ()-Getpaddingleft ()
-Getpaddingright (), Getmeasuredheight ()-Getpaddingtop ()
-Getpaddingbottom ()-mtextbound.height ());
int left = Getmeasuredwidth ()/2-BITMAPWIDTH/2;
int top = (getmeasuredheight ()-mtextbound.height ())/2-bitmapwidth
/2;
Set the drawing range of icon
Miconrect = new Rect (left, top, left + bitmapwidth, top + bitmapwidth);
} |
3. Draw the icon
There are many steps to drawing an icon, I'll make a list.
1, Compute alpha (default is 0)
2. Draw the original image
3, in the drawing area, draw a solid color block (set Alpha), this step is drawn on the memory of the bitmap
4, set mode, for the memory of the bitmap on the paint
5, Draw our icon, this step is drawn on the memory of the bitmap
6. Draw the original text
7. Draw text after setting alpha and color
8, the memory of the bitmap to draw out
According to the above steps, we can see that our icon is actually drawn two times, why should we draw the original image, because I think it looks better.
3-5 steps, that's the principle we analyzed above.
6-7 steps, is to draw the text, you can see that our text is implemented by setting Alpha
The code is as follows |
Copy Code |
@Override
protected void OnDraw (Canvas Canvas)
{
int alpha = (int) Math.ceil ((255 * malpha));
Canvas.drawbitmap (Miconbitmap, NULL, miconrect, NULL);
Setuptargetbitmap (Alpha);
Drawsourcetext (canvas, Alpha);
Drawtargettext (canvas, Alpha);
Canvas.drawbitmap (mbitmap, 0, 0, NULL);
}
private void Setuptargetbitmap (int alpha)
{
Mbitmap = Bitmap.createbitmap (Getmeasuredwidth (), Getmeasuredheight (),
config.argb_8888);
Mcanvas = new Canvas (MBITMAP);
Mpaint = new Paint ();
Mpaint.setcolor (Mcolor);
Mpaint.setantialias (TRUE);
Mpaint.setdither (TRUE);
Mpaint.setalpha (Alpha);
Mcanvas.drawrect (Miconrect, mpaint);
Mpaint.setxfermode (New Porterduffxfermode (PorterDuff.Mode.DST_IN));
Mpaint.setalpha (255);
Mcanvas.drawbitmap (Miconbitmap, NULL, Miconrect, mpaint);
}
private void Drawsourcetext (Canvas Canvas, int alpha)
{
Mtextpaint.settextsize (mtextsize);
Mtextpaint.setcolor (0xff333333);
Mtextpaint.setalpha (255-alpha);
Canvas.drawtext (Mtext, Miconrect.left + miconrect.width ()/2
-Mtextbound.width ()/2,
Miconrect.bottom + mtextbound.height (), mtextpaint);
}
private void Drawtargettext (Canvas Canvas, int alpha)
{
Mtextpaint.setcolor (Mcolor);
Mtextpaint.setalpha (Alpha);
Canvas.drawtext (Mtext, Miconrect.left + miconrect.width ()/2
-Mtextbound.width ()/2,
Miconrect.bottom + mtextbound.height (), mtextpaint);
}
|
About the calculation of the drawing text area, first is the starting point X:miconrect.left + miconrect.width ()/2-mtextbound.width ()/2 a bit long ha, text Miconrect.left + Miconrect.width ()/2 This position, in the icon horizontal area of the center point, this should not be questioned; the midpoint of the horizontal area of the icon-mtextbound.width ()/2 begins to draw the text, whether it is centered under the icon;
One might ask: How do you know the text width is less than the icon, I have 5 words to do? 5 words how, is still centered display, do not believe you try ~ ~
4, publish the method of setting up the transparency
By this, our icon control has been written, but we have not yet released the method of controlling the icon:
The code is as follows |
Copy Code |
public void Seticonalpha (float alpha) { This.malpha = Alpha; Invalidateview (); } private void Invalidateview () { if (looper.getmainlooper () = = Looper.mylooper ()) { & nbsp invalidate (); } else { & nbsp; postinvalidate (); } } |
We call Seticonalpha, avoid and Setalpha conflict, after the setup is complete, invalidate ~ ~ ~ ~
This is really the end, then see usage.
4. Actual Combat
1. layout file
The code is as follows |
Copy Code |
<linearlayout xmlns:android= "Http://schemas.android.com/apk/res/android"
Xmlns:zhy= "Http://schemas.android.com/apk/res/com.zhy.weixin6.ui"
Xmlns:tools= "Http://schemas.android.com/tools"
Android:layout_width= "Match_parent"
android:layout_height= "Match_parent"
android:orientation= "Vertical" >
<android.support.v4.view.viewpager
Android:id= "@+id/id_viewpager"
Android:layout_width= "Fill_parent"
android:layout_height= "0DP"
android:layout_weight= "1" >
</android.support.v4.view.ViewPager>
<linearlayout
Android:layout_width= "Fill_parent"
android:layout_height= "60DP"
android:background= "@drawable/TABBG"
android:orientation= "Horizontal" >
<com.zhy.weixin6.ui.changecoloriconwithtextview
Android:id= "@+id/id_indicator_one"
Android:layout_width= "0DP"
android:layout_height= "Fill_parent"
android:layout_weight= "1"
Android:padding= "5DP"
zhy:icon= "@drawable/ic_menu_start_conversation"
zhy:text= "@string/tab_weixin"
Zhy:text_size= "12SP"/>
<com.zhy.weixin6.ui.changecoloriconwithtextview
Android:id= "@+id/id_indicator_two"
Android:layout_width= "0DP"
android:layout_height= "Fill_parent"
android:layout_weight= "1"
Android:padding= "5DP"
zhy:icon= "@drawable/ic_menu_friendslist"
zhy:text= "@string/tab_contact"
Zhy:text_size= "12SP"/>
<com.zhy.weixin6.ui.changecoloriconwithtextview
Android:id= "@+id/id_indicator_three"
Android:layout_width= "0DP"
android:layout_height= "Fill_parent"
android:layout_weight= "1"
Android:padding= "5DP"
zhy:icon= "@drawable/ic_menu_emoticons"
zhy:text= "@string/tab_find"
Zhy:text_size= "12SP"/>
<com.zhy.weixin6.ui.changecoloriconwithtextview
Android:id= "@+id/id_indicator_four"
Android:layout_width= "0DP"
android:layout_height= "Fill_parent"
android:layout_weight= "1"
Android:padding= "5DP"
zhy:icon= "@drawable/ic_menu_allfriends"
zhy:text= "@string/tab_me"
Zhy:text_size= "12SP"/>
</LinearLayout>
</LinearLayout>
|
2, Mainactivity
The code is as follows |
Copy Code |
Package com.zhy.weixin6.ui;
Import Java.lang.reflect.Field;
Import Java.lang.reflect.Method;
Import java.util.ArrayList;
Import java.util.List;
Import Android.annotation.SuppressLint;
Import Android.os.Bundle;
Import android.support.v4.app.Fragment;
Import android.support.v4.app.FragmentActivity;
Import Android.support.v4.app.FragmentPagerAdapter;
Import Android.support.v4.view.ViewPager;
Import Android.support.v4.view.ViewPager.OnPageChangeListener;
Import Android.view.Menu;
Import Android.view.View;
Import Android.view.View.OnClickListener;
Import android.view.ViewConfiguration;
Import Android.view.Window;
@SuppressLint ("Newapi")
public class Mainactivity extends fragmentactivity implements
Onpagechangelistener, Onclicklistener
{
Private Viewpager Mviewpager;
Private list<fragment> mtabs = new arraylist<fragment> ();
Private Fragmentpageradapter Madapter;
Private string[] Mtitles = new string[] {"A-fragment!",
"Second fragment!", "Third fragment!", "Fourth Fragment!"};
Private list<changecoloriconwithtextview> Mtabindicator = new arraylist<changecoloriconwithtextview> ();
@Override
protected void OnCreate (Bundle savedinstancestate)
{
Super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Setoverflowshowingalways ();
Getactionbar (). setdisplayshowhomeenabled (false);
Mviewpager = (Viewpager) Findviewbyid (R.id.id_viewpager);
Initdatas ();
Mviewpager.setadapter (Madapter);
Mviewpager.setonpagechangelistener (this);
}
private void Initdatas ()
{
for (String title:mtitles)
{
Tabfragment tabfragment = new Tabfragment ();
Bundle args = new Bundle ();
Args.putstring ("title", title);
Tabfragment.setarguments (args);
Mtabs.add (tabfragment);
}
Madapter = new Fragmentpageradapter (Getsupportfragmentmanager ())
{
@Override
public int GetCount ()
{
return Mtabs.size ();
}
@Override
Public Fragment getitem (int arg0)
{
Return Mtabs.get (arg0);
}
};
Inittabindicator ();
}
@Override
public boolean Oncreateoptionsmenu (Menu menu)
{
Getmenuinflater (). Inflate (R.menu.main, menu);
return true;
}
private void Inittabindicator ()
{
Changecoloriconwithtextview one = (Changecoloriconwithtextview) Findviewbyid (R.id.id_indicator_one);
Changecoloriconwithtextview two = (Changecoloriconwithtextview) Findviewbyid (r.id.id_indicator_two);
Changecoloriconwithtextview three = (Changecoloriconwithtextview) Findviewbyid (R.id.id_indicator_three);
Changecoloriconwithtextview four = (Changecoloriconwithtextview) Findviewbyid (R.id.id_indicator_four);
Mtabindicator.add (one);
Mtabindicator.add (two);
Mtabindicator.add (three);
Mtabindicator.add (four);
One.setonclicklistener (this);
Two.setonclicklistener (this);
Three.setonclicklistener (this);
Four.setonclicklistener (this);
One.seticonalpha (1.0f);
}
@Override
public void onpageselected (int arg0)
{
}
@Override
public void onpagescrolled (int position, float positionoffset,
int positionoffsetpixels)
{
LOG.E ("TAG", "position =" + position + ", Positionoffset ="
+ Positionoffset);
if (Positionoffset > 0)
{
Changecoloriconwithtextview left = mtabindicator.get (position);
Changecoloriconwithtextview right = Mtabindicator.get (position + 1);
Left.seticonalpha (1-positionoffset);
Right.seticonalpha (Positionoffset);
}
}
@Override
public void onpagescrollstatechanged (int state)
{
}
@Override
public void OnClick (View v)
{
Resetothertabs ();
Switch (V.getid ())
{
Case R.id.id_indicator_one:
Mtabindicator.get (0). Seticonalpha (1.0f);
Mviewpager.setcurrentitem (0, false);
Break
Case R.id.id_indicator_two:
Mtabindicator.get (1). Seticonalpha (1.0f);
Mviewpager.setcurrentitem (1, false);
Break
Case R.id.id_indicator_three:
Mtabindicator.get (2). Seticonalpha (1.0f);
Mviewpager.setcurrentitem (2, false);
Break
Case R.id.id_indicator_four:
Mtabindicator.get (3). Seticonalpha (1.0f);
Mviewpager.setcurrentitem (3, false);
Break
}
}
/**
* Reset Other tab
*/
private void Resetothertabs ()
{
for (int i = 0; i < mtabindicator.size (); i++)
{
Mtabindicator.get (i). Seticonalpha (0);
}
}
@Override
public boolean onmenuopened (int featureid, menu menu)
{
if (Featureid = = window.feature_action_bar && menu!= null)
{
if (Menu.getclass (). Getsimplename (). Equals ("Menubuilder"))
{
Try
{
Method M = Menu.getclass (). Getdeclaredmethod (
"Setoptionaliconsvisible", Boolean.type);
M.setaccessible (TRUE);
M.invoke (menu, true);
catch (Exception e)
{
}
}
}
Return super.onmenuopened (Featureid, menu);
}
private void Setoverflowshowingalways ()
{
Try
{
True if a permanent menu key is present, false otherwise.
viewconfiguration config = viewconfiguration.get (this);
Field Menukeyfield = Viewconfiguration.class
. Getdeclaredfield ("Shaspermanentmenukey");
Menukeyfield.setaccessible (TRUE);
Menukeyfield.setboolean (config, false);
catch (Exception e)
{
E.printstacktrace ();
}
}
}
Activity inside the code although no comment, but very simple ha, is to initialize fragment, get our adapter, and then set to Viewpager;
Inittabindicator We initialize our custom controls, plus the Click event;
The only one that needs to be pointed out is:
We are in the onpagescrolled, dynamic acquisition of position and Positionoffset, and then get about two view, set Positionoffset;
Here expressed ashamed, once in high imitation micro-letter 5.2.1 Main interface architecture contains message notification onpagescrolled wrote a bunch of if else, in the video online, also have students immediately put forward, a line of code to fix ~ ~
So, we have a simple look at the next law, there is no if else's figure ~ ~ ~
There are still two ways to reflect, is to control the Actionbar icon, and click the menu button, the Actionbar menu displayed in the normal area ~ ~
3, Tabfragment
Package com.zhy.weixin6.ui;
Import Android.graphics.Color;
Import Android.os.Bundle;
Import android.support.v4.app.Fragment;
Import android.view.Gravity;
Import Android.view.LayoutInflater;
Import Android.view.View;
Import Android.view.ViewGroup;
Import Android.widget.TextView;
public class Tabfragment extends Fragment
{
Private String Mtitle = "Default";
Public Tabfragment ()
{
}
@Override
Public View Oncreateview (layoutinflater inflater, ViewGroup container,
Bundle savedinstancestate)
{
if (getarguments ()!= null)
{
Mtitle = Getarguments (). getString ("title");
}
TextView TextView = new TextView (getactivity ());
Textview.settextsize (20);
Textview.setbackgroundcolor (Color.parsecolor ("#ffffffff"));
Textview.setgravity (Gravity.center);
Textview.settext (Mtitle);
return textView;
}
}
|
Well, the whole case is over for us.
You can set a variety of colors in the layout file, 4 different colors can also play it!