Android high imitation WeChat 6.0 main interface with you to switch the icon color, android high imitation micro

Source: Internet
Author: User
Tags drawtext

Android high imitation 6.0 main interface with you to switch the icon color, android high imitation micro
Reprinted please indicate the source: bytes

Learning Android will inevitably imitate the interfaces of various apps. Since the advent of Android 6.0, I feel that the color-changing Tab icon is awesome. Today I will bring you custom controls, it will change your color to fly ~~

Well, let's take a look at it first:


The definition is not very good. Let's take a look ~~ Some wood may think that the color is too weak. I will change the color by moving my finger below:


Is this color a little cool ~~~ Okay ~ The following describes the principles.

2. Principles

As you may have guessed from the above, our icons are not two images, but one image, and the target color is customizable. Who can talk about personalization at will.

So how can we do this to make the icons change color as you like? In fact, the principle has appeared many times in my blog. here you will see a familiar figure:


Is there any familiar sense? we actually use the Xfermode of Paint. This time we use: Mode. DST_IN.

Dst_IN: review the effect. First, draw Dst, set Mode, and draw Src. Then, the intersection area of the drawing is displayed, and it is Dst.

Then, take a closer look at our icons:


For your convenience, I chose the non-transparent area of our icons with ps. We can see that the non-transparent area of our small robot is the part that is framed.

Then, the principle of changing the color of the icon appears:

1. First draw a color (for example, pink)

2. Set Mode = DST_IN.

3. Draw our cute little robot

Answer me, show what, show intersection, what is intersection? Intersection is the non-transparent area of our small robot, that is, the face, except for two eyes;

Well, how can we change the color?

Can't I set alpha when I draw a color ~~~

At this point, you should have understood the principle of drawing our icons.

If you are not familiar with the Mode, we recommend that you move to: Android custom controls to achieve the scratch effect is really just a scratch card?


3. Custom icon controls

We do not need to mention the entire interface, which is ViewPager + Fragment. Now we focus on the bottom ~~

Next, we will consider the Tab at the bottom. The Tab layout is LinearLayout, with four internal views. We can set weight to achieve equal share ~~

This View is our custom icon control, which is called ChangeColorIconWithTextView.

Next, we will consider what attributes should be published

1. Custom Attributes

After thinking about it, I decided to use the four attributes, icon color, text displayed under the icon, and text size, as custom attributes.

Then the Custom Attributes start:

A. values/attr. xml

<?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. Use it in the layout File

 <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 format. xmlns: zhy = "http://schemas.android.com/apk/res/application package name ".

C. obtain from the constructor

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; /*** restrict the range of icons to be drawn */private Rect mIconRect;/*** text at the bottom of the icon */private String mText = ""; private int mTextSize = (int) TypedValue. applyDimension (TypedValue. COMPLEX_UNIT_SP, 10, getResources (). getDisplayMetrics (); private Paint mTextPaint; private Rect mTextBound = new Rect (); public ChangeColorIconWithTextView (Context context) {super (context );} /*** initialize the custom property value ** @ param context * @ param attrs */public ChangeColorIconWithTextView (Context context, AttributeSet attrs) {super (context, attrs ); // obtain the configured icon TypedArray a = context. obtainStyledAttributes (attrs, R. styleable. changeColorIconView); int n =. getIndexCount (); for (int I = 0; I <n; I ++) {int attr =. getIndex (I); switch (attr) {case R. styleable. changeColorIconView_icon: BitmapDrawable drawable = (BitmapDrawable). getDrawable (attr); mIconBitmap = drawable. getBitmap (); break; case R. styleable. changeColorIconView_color: mColor =. getColor (attr, 0x45C01A); break; case R. styleable. changeColorIconView_text: mText =. getString (attr); break; case R. styleable. changeColorIconView_text_size: mTextSize = (int). getDimension (attr, TypedValue. applyDimension (TypedValue. COMPLEX_UNIT_SP, 10, getResources (). getDisplayMetrics (); break;}. recycle (); mTextPaint = new Paint (); mTextPaint. setTextSize (mTextSize); mTextPaint. setColor (0xff555555); // obtain the text painting range: mTextPaint. getTextBounds (mText, 0, mText. length (), mTextBound );}

We can see that we have obtained custom attributes in the constructor and computed the control occupied by text in our mTextBound.

2. Select the drawing area of the icon

Now that we have properties, we need to draw a text and an icon above the text. How can we control the area to be drawn?
The display area of our View is in the following three situations:


In these three cases, what is the edge length of my door icon?

I think the side length should be: the height of the control-the height of the text-the small value of the padding and the width-the padding of the control; let's give it a closer look;

Now, with the conclusion of the edge length above, we start to calculate the draw range of the icon:

@ Overrideprotected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {super. onMeasure (widthMeasureSpec, heightMeasureSpec); // obtain the width of the drawn 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 icon's painting range mIconRect = new Rect (left, top, left + bitmapWidth, top + bitmapWidth );}

3. Draw icons

There are many steps to draw an icon. Let me list one column.

1. Calculate alpha (0 by default)

2. Drawing the source Image

3. In the drawing area, draw a solid color block (with alpha set). This step is drawn on the memory bitmap.

4. Set the mode for the paint on the bitmap in the memory.

5. Draw our icons. This step is drawn on the memory bitmap.

6. Draw the original text

7. Draw text after Setting alpha and color

8. Draw the bitmap in memory

According to the above steps, we can see that our icons are actually drawn twice. Why do we need to draw the source image? I think it looks nice.

Step 3-5 is the analysis principle above

Step 6-7: Draw the text. We can see that our text is implemented by setting alpha.

@Overrideprotected 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);}

The calculation of the text area is based on the starting point x: mIconRect. left + mIconRect. width ()/2-mTextBound. width ()/2 is a bit long. The text is mIconRect. left + mIconRect. width ()/2, which is in the center of the horizontal area of the icon. width ()/2 starts to draw text, is it centered under the icon;

Some may ask: How do you know that the text width is smaller than the icon? What should I do if I have five words? The five characters are displayed in the center. Do not believe it ~~

4. Publish methods for setting transparency

At this point, we have finished writing the icon control, but we have not put out the method of controlling the icon:

public void setIconAlpha(float alpha){this.mAlpha = alpha;invalidateView();}private void invalidateView(){if (Looper.getMainLooper() == Looper.myLooper()){invalidate();} else{postInvalidate();}}

This is called setIconAlpha, which avoids conflicts with setAlpha. After the setting is complete, invalidate ~~~


This is the end. Next, let's look at the usage.


4. Practice
1. layout File

<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

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. suppo Rt. 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 implementsOnPageChangeListener, OnClickListener {private ViewPager mViewPager; private List <Fragment> mTabs = new ArrayList <Fragme Nt> (); private FragmentPagerAdapter mAdapter; private String [] mTitles = new String [] {"First Fragment! "," Second Fragment! "," Third Fragment! "," Fourth Fragment! "}; Private List <ChangeColorIconWithTextView> mTabIndicator = new ArrayList <ChangeColorIconWithTextView> (); @ Overrideprotected 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. setAd Apter (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 () {@ Overridepublic int getCount () {return mTabs. size () ;}@ Overridepubli C Fragment getItem (int arg0) {return mTabs. get (arg0) ;}}; initTabIndicator () ;}@ Overridepublic 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. I D. 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. setOnClickListe Ner (this); four. setOnClickListener (this); one. setIconAlpha (1.0f) ;}@ Overridepublic void onPageSelected (int arg0) {}@ Overridepublic void onPageScrolled (int position, float positionOffset, int positionOffsetPixels) {// Log. e ("TAG", "position =" + position + ", positionOffset =" // + positionOffset); if (positionOffset> 0) {ChangeColorIconWithTextView left = mTabIndicator. get (position); ChangeColorIconWith TextView right = mTabIndicator. get (position + 1); left. setIconAlpha (1-positionOffset); right. setIconAlpha (positionOffset); }}@ Overridepublic void onPageScrollStateChanged (int state) {}@ Overridepublic 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: mTabIndic Ator. 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 another Tab */private void resetOtherTabs () {for (int I = 0; I <mTabIndicator. size (); I ++) {mTabIndica Tor. get (I). setIconAlpha (0) ;}@ Overridepublic 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 ();}}}

Although the Code in the Activity has no comments, it is very simple. It is to initialize Fragment, get our adapter, and then set it to ViewPager;

InitTabIndicator we initialize our custom controls and add click events;

The only one that needs to be pointed out is:

In onPageScrolled, We dynamically obtain the position and positionOffset, then get the two views left and right, and set positionOffset;

Here, I am ashamed to say that I wrote a bunch of if else IN THE onPageScrolled of the main interface architecture of the high imitation 5.2.1 containing message notifications. After the video went online, some people immediately proposed it, complete a line of code ~~

Therefore, we have found a simple rule here, and there is no such thing as if else ~~~

There are two remaining reflection methods: Controlling the Actionbar icon and clicking the menu button to display the menu of the ActionBar 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(){}@Overridepublic 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;}}



Now, our entire case is over ~~

You can set a variety of colors in the layout file. You can also set four different colors to enjoy yourself ~~



Download source code





I have created a QQ Group for your convenience. Group Number:55032675

Bytes ----------------------------------------------------------------------------------------------------------

Some of the bloggers have already been online. If you do not like boring text, stamp it (for initial record, we look forward to your support ):

1. High imitation 5.2.1 main interface and message reminder

2. High imitation QQ5.0 slide

3. Implementation of Android intelligent robot xiaomu







Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.