转载

微信5.0之Fragment使用

相信大家对于微信5.0的切换效果一定很有印象,对于一些童鞋一定认为这是通过TabHost实现的,不过这里我要纠正一下你们的错误观点了,这个效果的实现是通过Fragment+ViewPage实现的,看上去简单的滑动切换,里面包含了很多腾讯工程师对于Android UI设计的独特视角和超强的业务能力,真心为他们点一个赞。说了这么多,下面我们开始探讨如何实现这样炫酷的效果,开始之前建议大家先看一下关于Fragment的介绍,这样会更好的帮助我们理解今天要介绍的知识。

我们本篇最后的设计效果:

微信5.0之Fragment使用

下面我们开始今天的代码解析,让我们一起学习吧。

我们项目的目录结构:

微信5.0之Fragment使用

第一步:创建自定义View实现底部切换按钮

对于微信主界面底部有4个类似按钮的小图标,这些小图标会随着我们滑动事件的改变而改变,开始绘制之前我们需要准备4张小图片,为我们接下来的开发做好准备。自定义View的代码:

public class ChangeColorIconWithTextView extends View {  private Bitmap mBitmap;  private Canvas mCanvas;  private Paint mPaint;  /**   * 颜色   */  private int mColor = 0xFF45C01A;  /**   * 透明度 0.0-1.0   */  private float mAlpha = 0f;  /**   * 图标   */  private Bitmap mIconBitmap;  /**   * 限制绘制icon的范围   */  private Rect mIconRect;  /**   * 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);  }  /**   * 初始化自定义属性值   *    * @param context   * @param attrs   */  public ChangeColorIconWithTextView(Context context, AttributeSet attrs)  {   super(context, attrs);   // 获取设置的图标   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);   // 得到text绘制范围   mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);  }  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  {   super.onMeasure(widthMeasureSpec, heightMeasureSpec);   // 得到绘制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;   // 设置icon的绘制范围   mIconRect = new Rect(left, top, left + bitmapWidth, top + bitmapWidth);  }  @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);  }  public void setIconAlpha(float alpha)  {   this.mAlpha = alpha;   invalidateView();  }  private void invalidateView()  {   if (Looper.getMainLooper() == Looper.myLooper())   {    invalidate();   } else   {    postInvalidate();   }  }  public void setIconColor(int color)  {   mColor = color;  }  public void setIcon(int resId)  {   this.mIconBitmap = BitmapFactory.decodeResource(getResources(), resId);   if (mIconRect != null)    invalidateView();  }  public void setIcon(Bitmap iconBitmap)  {   this.mIconBitmap = iconBitmap;   if (mIconRect != null)    invalidateView();  }  private static final String INSTANCE_STATE = "instance_state";  private static final String STATE_ALPHA = "state_alpha";  @Override  protected Parcelable onSaveInstanceState()  {   Bundle bundle = new Bundle();   bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());   bundle.putFloat(STATE_ALPHA, mAlpha);   return bundle;  }  @Override  protected void onRestoreInstanceState(Parcelable state)  {   if (state instanceof Bundle)   {    Bundle bundle = (Bundle) state;    mAlpha = bundle.getFloat(STATE_ALPHA);    super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE));   } else   {    super.onRestoreInstanceState(state);   }  } } 

第二步:设置自定义属性

在我们工程目录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> 

第三步:设置一个自定义属性

我们的Layout文件夹下新建一个drawable文件夹,在里面新建一个tabbg.xml:

<?xml version="1.0" encoding="utf-8"?> <!-- 布局文件LinearLayout --> <shape xmlns:android="http://schemas.android.com/apk/res/android" >     <stroke android:width="1dp" android:color="#eee" />     <solid android:color="#F7F7F7"/> </shape>

第四步:设置主界面底部显示的文字

打开string.xml添加文字定义:

<?xml version="1.0" encoding="utf-8"?> <resources>  <string name="app_name">微信</string>  <string name="tab_weixin">one</string>  <string name="tab_contact">two</string>  <string name="tab_find">three</string>  <string name="tab_me">four</string> </resources> 

第五步:布局文件

<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> 

注意红色标注处xmlns:zhy="http://schemas.android.com/apk/res/com.zhy.weixin6.ui";com.zhy.weixin6.ui为工程包名。自定义属性的使用通过zhy引用。

第六步:我们的Fragment创建

public class oneFragment extends Fragment {  private String mTitle = "one";  public oneFragment()  {  }  @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;  } } 

第七步:主Activity

@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[] { "First 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);   mViewPager = (ViewPager) findViewById(R.id.id_viewpager);   initDatas();   mViewPager.setAdapter(mAdapter);   mViewPager.setOnPageChangeListener(this);  }  private void initDatas()  {   for (String title : mTitles)   {    oneFragment tabFragment = new oneFragment();    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();  }  //初始化按钮,设置点击监听  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)  {   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;   }  }  /**   * 重置其他的Tab   */  private void resetOtherTabs()  {   for (int i = 0; i < mTabIndicator.size(); i++)   {    mTabIndicator.get(i).setIconAlpha(0);   }  } } 

到这里我们的微信5.0主界面设计效果就实现完毕,大家可以测试一下,有什么疑问,欢迎留言讨论。下一篇:Fragment使用

正文到此结束
Loading...