你的位置:首页 > 操作系统

[操作系统]微信5.0之Fragment使用


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

<?

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

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

<?

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

  打开string.

<?

  第五步:布局文件

<LinearLayout     ="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>

  注意红色标注处

  第六步:我们的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使用