网站地图    收藏   

主页 > 后端 > 微信开发 >

仿微信主界面 - 微信公众平台开发:微信公众号

来源:自学PHP网    时间:2015-04-14 12:58 作者: 阅读:

[导读] 跟着慕课网的教学视频学习了如何制作微信的主界面,因为还有一些地方并没有完全搞懂,所以这里主要是记录下整个制作的过程,方便以后的学习!效果图如图所示:实现了点击下面...

跟着慕课网的教学视频学习了如何制作微信的主界面,因为还有一些地方并没有完全搞懂,所以这里主要是记录下整个制作的过程,方便以后的学习!

效果图如图所示:

\\

实现了点击下面tab切换fragment以及滑动切换tab的功能,同时滑动时,下面tab的icon会实现颜色渐变的效果。

首先是主界面的布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bunschen="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="@drawable/tab_bg"
        android:orientation="horizontal">

        <com.chen.weixin_6_0.ChangeIconColorWithText
            android:id="@+id/tab_indicator_one"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            bunschen:Icon="@drawable/ic_menu_start_conversation"
            bunschen:color="#FF008901"
            bunschen:text="@string/app_name"
            bunschen:text_size="12sp"/>

        <com.chen.weixin_6_0.ChangeIconColorWithText
            android:id="@+id/tab_indicator_two"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            bunschen:Icon="@drawable/ic_menu_friendslist"
            bunschen:color="#FF008901"
            bunschen:text="@string/tab_contact"
            bunschen:text_size="12sp"/>

        <com.chen.weixin_6_0.ChangeIconColorWithText
            android:id="@+id/tab_indicator_three"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            bunschen:Icon="@drawable/ic_menu_emoticons"
            bunschen:color="#FF008901"
            bunschen:text="@string/tab_find"
            bunschen:text_size="12sp"/>

        <com.chen.weixin_6_0.ChangeIconColorWithText
            android:id="@+id/tab_indicator_four"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            bunschen:Icon="@drawable/ic_menu_allfriends"
            bunschen:color="#FF008901"
            bunschen:text="@string/tab_me"
            bunschen:text_size="12sp"/>

    </LinearLayout>

</LinearLayout>
activity_mian

主界面采用线型布局,上面是自定义的ActionBar,中间内容区域是ViewPager+Fragment,下面的Tab区域是一个横向线型布局,其中每个View都是通过自定义布局实现。

1.自定义ActionBar:

//是更多菜单按钮显示出来
private void setOverflowShowingAlways() {
try {
  ViewConfiguration config = ViewConfiguration.get(this);
  Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
  menuKeyField.setAccessible(true);
  menuKeyField.setBoolean(config, false);
  } catch (Exception e) {
    e.printStackTrace();
  }
}

该段是通过反射机制,将OverflowButton显示出来,因为在有菜单实体按键的手机中,屏幕中的菜单选项不会显示出来。

//是更多菜单按钮显示出来
private void setOverflowShowingAlways() {
try {
  ViewConfiguration config = ViewConfiguration.get(this);
  Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
  menuKeyField.setAccessible(true);
  menuKeyField.setBoolean(config, false);
  } catch (Exception e) {
    e.printStackTrace();
  }
}

这段也是通过反射机制将Overflow菜单展开的菜单选项中将图标也显示出来,因为默认是将Overflow菜单展开的菜单选项的突变隐藏掉的。

菜单布局:

  <menu xmlns:android="http://schemas.android.com/apk/res/android">
      <item
          android:id="@+id/action_settings"
          android:actionViewClass="android.widget.SearchView"
          android:icon="@drawable/actionbar_search_icon"
          android:showAsAction="ifRoom|collapseActionView"
          android:title="@string/action_search"
          />
  
     <item
         android:id="@+id/menu_contact"
         android:icon="@drawable/menu_group_chat_icon"
         android:title="@string/menu_contact"/>
 
     <item
         android:id="@+id/menu_add_friend"
         android:icon="@drawable/menu_add_icon"
         android:title="@string/menu_add_friend"/>
 
     <item
         android:id="@+id/menu_scan"
         android:icon="@drawable/men_scan_icon"
         android:title="@string/menu_contact"/>
 
     <item
         android:id="@+id/menu_feedback"
         android:icon="@drawable/menu_feedback_icon"
         android:title="@string/menu_feedback"/>
 
 </menu>

接下来最主要的就是自定义View

首先是定义自定义的View需要的一些属性

values/attrs.xml:

  <?xml version="1.0" encoding="utf-8"?>
  <resources>
 
      <attr name="Icon" format="reference"></attr>
      <attr name="color" format="color"></attr>
      <attr name="text" format="string"></attr>
      <attr name="text_size" format="dimension"></attr>
      
      <declare-styleable name="ChangeIconColorWithText">
         <attr name="Icon"></attr>
         <attr name="color"></attr>
         <attr name="text"></attr>
         <attr name="text_size"></attr>
     </declare-styleable>
 </resources>

然后是在布局文件中使用:

 <com.chen.weixin_6_0.ChangeIconColorWithText
             android:id="@+id/tab_indicator_one"
             android:layout_width="0dp"
             android:layout_height="match_parent"
             android:layout_weight="1"
             bunschen:Icon="@drawable/ic_menu_start_conversation"
             bunschen:color="#FF008901"
             bunschen:text="@string/app_name"
             bunschen:text_size="12sp"/>

注意这里的自定义的命名空间:

bunschen:Icon="@drawable/ic_menu_start_conversation"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bunschen="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

这里在开头自定义了命名空间,所以可以使用自定义的属性。

然后就是在构造函数中获取View:

   public class ChangeIconColorWithText extends View {
   
       private int mColor = 0xFF008901;
       private Bitmap mIconBitmap;
       private String mText = "微信";
       private int mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
               12, getResources().getDisplayMetrics());
   
       private Bitmap mBitmap;
      private Canvas mCanvas;
      private Paint mPaint;
      private float alpha;
      private Rect mTextBounds;
      private Rect mBitmapBounds;
      private Paint textPaint;
  
      private final static String INSTANCE_STATUS = "instance_status";
      private final static String ALPHA_STATUS = "alpha_status";
  
      public ChangeIconColorWithText(Context context) {
          this(context, null);
      }
  
      public ChangeIconColorWithText(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
      }
  
      public ChangeIconColorWithText(Context context, AttributeSet attrs, int defStyleAttr) {
          super(context, attrs, defStyleAttr);
          //获取到布局文件中定义的自定义控件的属性
          TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ChangeIconColorWithText);
          int n = typedArray.getIndexCount();
          //将这些属性赋值给该控件的成员变量
          for (int i = 0; i < n; i++) {
              int attr = typedArray.getIndex(i);
              switch (attr) {
                  case R.styleable.ChangeIconColorWithText_color:
                      mColor = typedArray.getColor(attr, 0xFF0E4010);
                     break;
                  case R.styleable.ChangeIconColorWithText_Icon:
                      BitmapDrawable drawable = (BitmapDrawable) typedArray.getDrawable(attr);
                     mIconBitmap = drawable.getBitmap();
                      break;
                  case R.styleable.ChangeIconColorWithText_text:
                      mText = typedArray.getString(attr);
                      break;
                 case R.styleable.ChangeIconColorWithText_text_size:
                      mTextSize = (int) typedArray.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                              12, getResources().getDisplayMetrics()));
                      break;
              }
          }
          //回收掉使用的资源
          typedArray.recycle();
          
          mTextBounds = new Rect();
          textPaint = new Paint();
          textPaint.setTextSize(mTextSize);
          textPaint.setColor(0xff555555);
          textPaint.getTextBounds(mText, 0, mText.length(), mTextBounds);
      }
  
      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          super.onMeasure(widthMeasureSpec, heightMeasureSpec);
          //测量图标的宽度,长度与宽度一致
          int iconWidth = Math.min(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
                  getMeasuredHeight() - getPaddingBottom() - getPaddingTop() - mTextBounds.height());
          //测量图标绘制的位置的上下左右的值
        int left = (getMeasuredWidth() - iconWidth)/2;
          int top = (getMeasuredHeight() - mTextBounds.height() - iconWidth)/2;
          //确定icon绘制的边界
          mBitmapBounds = new Rect(left,top,left+iconWidth,top+iconWidth);
      }
  
      @Override
      protected void onDraw(Canvas canvas) {
          super.onDraw(canvas);
          //绘制出原无颜色的图标
          canvas.drawBitmap(mIconBitmap,null,mBitmapBounds,null);
          //ceil() 方法执行的是向上取整计算,它返回的是大于或等于函数参数,并且与之最接近的整数
          int Alpha = (int) Math.ceil(255 * alpha);
          // 内存去准备mBitmap , setAlpha , 纯色 ,xfermode , 图标
          setupTargetBitmap(Alpha);
          //1.绘制原文本。
          setupSourceText(canvas,Alpha);
          //2.绘制变色文本
          setupTargetText(canvas,Alpha);
          //将内存中绘制出的Bitmap对象绘制出来
          canvas.drawBitmap(mBitmap,0,0,null);
      }
      //绘制带颜色的文本
      private void setupTargetText(Canvas canvas, int alpha) {
          textPaint.setColor(mColor);
          textPaint.setAlpha(alpha);
          //计算文本绘制的位置
          float x = (getMeasuredWidth() - mTextBounds.width())/2;
          float y = (mBitmapBounds.bottom + mTextBounds.height());
          canvas.drawText(mText,x,y,textPaint);
     }
     //绘制原文本
     private void setupSourceText(Canvas canvas, int alpha) {
         textPaint.setAlpha(255 - alpha);
         textPaint.setColor(0xff333333);
         float x = (getMeasuredWidth() - mTextBounds.width())/2;
         float y = (mBitmapBounds.bottom + mTextBounds.height());
         canvas.drawText(mText,x,y,textPaint);
     }
     //在内存中绘制出icon
     private void setupTargetBitmap(int alpha) {
         mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
                 Bitmap.Config.ARGB_8888);
         mCanvas = new Canvas(mBitmap);
         mPaint = new Paint();
         mPaint.setColor(mColor);
         mPaint.setAntiAlias(true);
         mPaint.setDither(true);
         mPaint.setAlpha(alpha);
         mCanvas.drawRect(mBitmapBounds, mPaint);
         //设置显示纯色区域与图标的交集区域,即显示的是图标以及颜色为纯色区域的颜色
         mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
         mPaint.setAlpha(255);
         mCanvas.drawBitmap(mIconBitmap, null, mBitmapBounds, mPaint);
     }
     //设置alpha值
     public void setAlphaView(float alpha){
         this.alpha = alpha;
         invalidateView();
     }
     //当alpha值变化时,重绘视     private void invalidateView() {
         //判断是否是在UI线程
         if(Looper.getMainLooper() == Looper.myLooper()){
             invalidate();
         }else{
             postInvalidate();
         }
     }
     //保存数据值及状态,防止Activity被系统销毁时在回到主界面时显示不正常的现象
     @Override
     protected Parcelable onSaveInstanceState() {
         Bundle bundle = new Bundle();
         bundle.putParcelable(INSTANCE_STATUS,super.onSaveInstanceState());
         bundle.putFloat(ALPHA_STATUS,alpha);
         return bundle;
     }
     //回复原先保存的数据值及状态
     @Override
     protected void onRestoreInstanceState(Parcelable state) {
         if(state instanceof Bundle){
             Bundle bundle = (Bundle) state;
            alpha = bundle.getFloat(ALPHA_STATUS);
             super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATUS));
             return;
         }
         super.onRestoreInstanceState(state);
     }
 }

然后是在MainActivity中实现滑动更新tab,以及点击tab更新fragment的逻辑:

   public class MainActivity extends FragmentActivity implements View.OnClickListener, ViewPager.OnPageChangeListener {
   
       private ViewPager viewPager;
       //fragment中显示的文本内容
       private String[] mTitles = new String[]{"first tab fragment", "second tab fragment",
               "third tab fragment", "fourth tab fragment"};
   
       private FragmentPagerAdapter mAdapter;
   
      private List<Fragment> mData = new ArrayList<>();
      //管理四个tab的List集合
      private List<ChangeIconColorWithText> tabList = new ArrayList<>();
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          setOverflowShowingAlways();
          getActionBar().setDisplayHomeAsUpEnabled(false);
  
          initView();
         initData();
          viewPager.setAdapter(mAdapter);
          viewPager.setOnPageChangeListener(this);
      }
  
      private void initData() {
          for(String title : mTitles){
              TabFragment tabFragment = new TabFragment();
              Bundle bundle = new Bundle();
              bundle.putString(TabFragment.TITLE,title);
              tabFragment.setArguments(bundle);
              mData.add(tabFragment);
          }
 
          mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
              @Override
              public Fragment getItem(int position) {
                  return mData.get(position);
              }
  
              @Override
              public int getCount() {
                  return mData.size();
              }
          };
      }
  
      private void initView() {
          viewPager = (ViewPager) findViewById(R.id.viewPager);
          ChangeIconColorWithText one = (ChangeIconColorWithText) findViewById(R.id.tab_indicator_one);
          tabList.add(one);
          ChangeIconColorWithText two = (ChangeIconColorWithText) findViewById(R.id.tab_indicator_two);
          tabList.add(two);
          ChangeIconColorWithText three = (ChangeIconColorWithText) findViewById(R.id.tab_indicator_three);
          tabList.add(three);
          ChangeIconColorWithText four = (ChangeIconColorWithText) findViewById(R.id.tab_indicator_four);
          tabList.add(four);
  
          one.setOnClickListener(this);
          two.setOnClickListener(this);
          three.setOnClickListener(this);
          four.setOnClickListener(this);
          resetOtherTab();
         one.setAlphaView(1);
     }
  
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          getMenuInflater().inflate(R.menu.menu_main, menu);
  
          return true;
     }
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          int id = item.getItemId();
  
          if (id == R.id.action_settings) {
              return true;
          }
          return super.onOptionsItemSelected(item);
      }
  
      //是更多菜单按钮显示出来
      private void setOverflowShowingAlways() {
          try {
              ViewConfiguration config = ViewConfiguration.get(this);
              Field menuKeyField = ViewConfiguration.class
                      .getDeclaredField("sHasPermanentMenuKey");
              menuKeyField.setAccessible(true);
              menuKeyField.setBoolean(config, false);
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  
      @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);
     }
 
     @Override
     public void onClick(View v) {
         resetOtherTab();
         switch(v.getId()){
             case R.id.tab_indicator_one:
                 tabList.get(0).setAlphaView(1);
                 viewPager.setCurrentItem(0,false);
                 break;
             case R.id.tab_indicator_two:
                 tabList.get(1).setAlphaView(1);
                 viewPager.setCurrentItem(1,false);
                 break;
             case R.id.tab_indicator_three:
                 tabList.get(2).setAlphaView(1);
                 viewPager.setCurrentItem(2,false);
                 break;
             case R.id.tab_indicator_four:
                 tabList.get(3).setAlphaView(1);
                 viewPager.setCurrentItem(3,false);
                 break;
         }
     }
 
     private void resetOtherTab() {         for(int i = 0; i < tabList.size(); i++){
             tabList.get(i).setAlphaView(0);
         }
     }
   //这里是在ViewPager滑动时,因为只有两个tab的颜色会发生变化,所以通过将他们的icon和文本颜色的alpha值进行改变,从而产生渐变的效果。
     @Override
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
         if(positionOffset > 0){
             ChangeIconColorWithText left = tabList.get(position);
             ChangeIconColorWithText right = tabList.get(position + 1);
 
             left.setAlphaView(1-positionOffset);
             right.setAlphaView(positionOffset);
         }
     }
 
     @Override
     public void onPageSelected(int position) {
 
     }
 
     @Override
     public void onPageScrollStateChanged(int state) {
 
     }

fragment:

  public class TabFragment extends Fragment {
  
      private static String mTitle = "default";
      public static final String TITLE = "title";
      @Override
      public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
          TextView tv = new TextView(getActivity());
          if(getArguments() != null) {
              mTitle = getArguments().getString(TITLE);
         }
         tv.setText(mTitle);
         tv.setTextSize(20);
         tv.setTextColor(Color.BLACK);
         tv.setGravity(Gravity.CENTER);
         return tv;
     }
 }

 基本内容就是这些,其中自定义View是难点,主要是自定义View中的绘制方法,XferMode的DST_IN方法。这里记录下来,以后慢慢学习。

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论