android高仿微信佈局(二)
阿新 • • 發佈:2019-02-18
前言
這期我們講講怎麼實現微信的左右滑動的效果和底部的tabs欄
廢話不多說,開工吧!
首先我們先看看總體佈局是怎麼寫的。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:hyman="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.poulwalker.demobar.AppBarActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="微信"
android:textColor="#ffffff"
android:textSize="20sp" />
</android.support.v7.widget.Toolbar>
<android.support.v4.view.ViewPager
android:id="@+id/id_viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</android.support.v4.view.ViewPager>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="55dp"
android:background="@drawable/tab_bg"
android:orientation="horizontal">
<com.example.poulwalker.demobar.ChangeColorIconWithText
android:id="@+id/id_indicator_one"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
hyman:icon="@mipmap/ic_weixin"
android:padding="5dp"
hyman:text="微信"
hyman:text_size="12sp"
hyman:color="#3F51B5"/>
<com.example.poulwalker.demobar.ChangeColorIconWithText
android:id="@+id/id_indicator_two"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
hyman:icon="@mipmap/ic_friend"
android:padding="5dp"
hyman:text="通訊錄"
hyman:text_size="12sp"
hyman:color="#3F51B5"/>
<com.example.poulwalker.demobar.ChangeColorIconWithText
android:id="@+id/id_indicator_three"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
hyman:icon="@mipmap/ic_find"
android:padding="5dp"
hyman:text="發現"
hyman:text_size="12sp"
hyman:color="#3F51B5"/>
<com.example.poulwalker.demobar.ChangeColorIconWithText
android:id="@+id/id_indicator_four"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
hyman:icon="@mipmap/ic_me"
android:padding="5dp"
hyman:text="我"
hyman:text_size="12sp"
hyman:color="#3F51B5"/>
</LinearLayout>
</LinearLayout>
關於第一個控制元件toolbar,我們在第一期已經講了。不懂的童鞋可以檢視上期講的內容。
根據佈局我們可以看到有ViewPager、還有ChangeColorIconWithText。其中ChangeColorIconWithText是自己定義的。這個佈局的效果是怎麼樣的呢?諸位開啟自己的手機微信就能看到啦。
接下來我們要在程式碼裡實現微信的左劃右劃和變色的功能。
ChangeColorIconWithText.java的實現
第一步定義。
private int mColor = 0xFF45C01A;
private Bitmap mIconBitmap;
private String mText = "微信";
private int mTextSize = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics());
private Canvas mCanvas;
private Bitmap mBitmap;
private Paint mPaint;
private float mAlpha;
private Rect mIconRect;
private Rect mTextBound;
private Paint mTextPaint;
public ChangeColorIconWithText(Context context)
{
this(context, null);
}
public ChangeColorIconWithText(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
第二步獲取自定義屬性的值
/**
* 獲取自定義屬性的值
*
* @param context
* @param attrs
* @param defStyleAttr
*/
public ChangeColorIconWithText(Context context, AttributeSet attrs,
int defStyleAttr)
{
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.ChangeColorIconWithText);
int n = a.getIndexCount();
for (int i = 0; i < n; i++)
{
int attr = a.getIndex(i);
switch (attr)
{
case R.styleable.ChangeColorIconWithText_icon:
BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr);
mIconBitmap = drawable.getBitmap();
break;
case R.styleable.ChangeColorIconWithText_color:
mColor = a.getColor(attr, 0xFF45C01A);
break;
case R.styleable.ChangeColorIconWithText_text:
mText = a.getString(attr);
break;
case R.styleable.ChangeColorIconWithText_text_size:
mTextSize = (int) a.getDimension(attr, TypedValue
.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12,
getResources().getDisplayMetrics()));
break;
}
}
a.recycle();
mTextBound = new Rect();
mTextPaint = new Paint();
mTextPaint.setTextSize(mTextSize);
mTextPaint.setColor(0Xff555555);
mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);
}
第三步各函式的定義
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int iconWidth = Math.min(getMeasuredWidth() - getPaddingLeft()
- getPaddingRight(), getMeasuredHeight() - getPaddingTop()
- getPaddingBottom() - mTextBound.height());
int left = getMeasuredWidth() / 2 - iconWidth / 2;
int top = getMeasuredHeight() / 2 - (mTextBound.height() + iconWidth)
/ 2;
mIconRect = new Rect(left, top, left + iconWidth, top + iconWidth);
}
@Override
protected void onDraw(Canvas canvas)
{
canvas.drawBitmap(mIconBitmap, null, mIconRect, null);
int alpha = (int) Math.ceil(255 * mAlpha);
// 記憶體去準備mBitmap , setAlpha , 純色 ,xfermode , 圖示
setupTargetBitmap(alpha);
// 1、繪製原文字 ; 2、繪製變色的文字
drawSourceText(canvas, alpha);
drawTargetText(canvas, alpha);
canvas.drawBitmap(mBitmap, 0, 0, null);
}
/**
* 繪製變色的文字
*
* @param canvas
* @param alpha
*/
private void drawTargetText(Canvas canvas, int alpha)
{
mTextPaint.setColor(mColor);
mTextPaint.setAlpha(alpha);
int x = getMeasuredWidth() / 2 - mTextBound.width() / 2;
int y = mIconRect.bottom + mTextBound.height();
canvas.drawText(mText, x, y, mTextPaint);
}
/**
* 繪製原文字
*
* @param canvas
* @param alpha
*/
private void drawSourceText(Canvas canvas, int alpha)
{
mTextPaint.setColor(0xff333333);
mTextPaint.setAlpha(255 - alpha);
int x = getMeasuredWidth() / 2 - mTextBound.width() / 2;
int y = mIconRect.bottom + mTextBound.height();
canvas.drawText(mText, x, y, mTextPaint);
}
/**
* 在記憶體中繪製可變色的Icon
*/
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 static final String INSTANCE_STATUS = "instance_status";
private static final String STATUS_ALPHA = "status_alpha";
@Override
protected Parcelable onSaveInstanceState()
{
Bundle bundle = new Bundle();
bundle.putParcelable(INSTANCE_STATUS, super.onSaveInstanceState());
bundle.putFloat(STATUS_ALPHA, mAlpha);
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state)
{
if (state instanceof Bundle)
{
Bundle bundle = (Bundle) state;
mAlpha = bundle.getFloat(STATUS_ALPHA);
super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATUS));
return;
}
super.onRestoreInstanceState(state);
}
public void setIconAlpha(float alpha)
{
this.mAlpha = alpha;
invalidateView();
}
/**
* 重繪
*/
private void invalidateView()
{
if (Looper.getMainLooper() == Looper.myLooper())
{
invalidate();
} else
{
postInvalidate();
}
}
TabFragment.java的實現
public class TabFragment extends Fragment
{
private String mTitle = "Default";
public static final String TITLE = "title";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
if (getArguments() != null)
{
mTitle = getArguments().getString(TITLE);
}
TextView tv = new TextView(getActivity());
tv.setTextSize(20);
tv.setBackgroundColor(Color.parseColor("#ffffffff"));
tv.setText(mTitle);
tv.setGravity(Gravity.CENTER);
return tv;
}
}
接下來就是在主活動裡呼叫了
public class AppBarActivity extends AppCompatActivity implements View.OnClickListener,ViewPager.OnPageChangeListener{}
第一步定義變數。
private ViewPager mViewPager;
private List<Fragment> mTabs = new ArrayList<Fragment>();
private String[] mTitles = new String[]
{ "First Fragment !", "Second Fragment !","Three Fragment !","four"};
private FragmentPagerAdapter mAdapter;
private List<ChangeColorIconWithText> mTabIndicators = new ArrayList<ChangeColorIconWithText>();
第二步,初始化所有事件
/**
* 初始化所有事件
*/
private void initEvent()
{
mViewPager.setOnPageChangeListener(this);
}
private void initView()
{
mViewPager = (ViewPager) findViewById(R.id.id_viewpager);
ChangeColorIconWithText one = (ChangeColorIconWithText) findViewById(R.id.id_indicator_one);
mTabIndicators.add(one);
ChangeColorIconWithText two = (ChangeColorIconWithText) findViewById(R.id.id_indicator_two);
mTabIndicators.add(two);
ChangeColorIconWithText three = (ChangeColorIconWithText) findViewById(R.id.id_indicator_three);
mTabIndicators.add(three);
ChangeColorIconWithText four = (ChangeColorIconWithText) findViewById(R.id.id_indicator_four);
mTabIndicators.add(four);
one.setOnClickListener(this);
two.setOnClickListener(this);
three.setOnClickListener(this);
four.setOnClickListener(this);
one.setIconAlpha(1.0f);
}
左劃右劃的實現
private void initDatas()
{
for (String title : mTitles)
{
TabFragment tabFragment = new TabFragment();
Bundle bundle = new Bundle();
bundle.putString(TabFragment.TITLE, title);
tabFragment.setArguments(bundle);
mTabs.add(tabFragment);
}
mAdapter = new FragmentPagerAdapter(getSupportFragmentManager())
{
@Override
public int getCount()
{
return mTabs.size();
}
@Override
public Fragment getItem(int position)
{
return mTabs.get(position);
}
};
}
點選事件及其餘函式的實現
@Override
public void onClick(View v) {
clickTab(v);
}
private void clickTab(View v) {
resetOtherTabs();
switch (v.getId())
{
case R.id.id_indicator_one:
mTabIndicators.get(0).setIconAlpha(1.0f);
mViewPager.setCurrentItem(0, false);
break;
case R.id.id_indicator_two:
mTabIndicators.get(1).setIconAlpha(1.0f);
mViewPager.setCurrentItem(1, false);
break;
case R.id.id_indicator_three:
mTabIndicators.get(2).setIconAlpha(1.0f);
mViewPager.setCurrentItem(2, false);
break;
case R.id.id_indicator_four:
mTabIndicators.get(3).setIconAlpha(1.0f);
mViewPager.setCurrentItem(3, false);
break;
}
}
private void resetOtherTabs() {
for (int i = 0; i < mTabIndicators.size(); i++)
{
mTabIndicators.get(i).setIconAlpha(0);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (positionOffset > 0)
{
ChangeColorIconWithText left = mTabIndicators.get(position);
ChangeColorIconWithText right = mTabIndicators.get(position + 1);
left.setIconAlpha(1 - positionOffset);
right.setIconAlpha(positionOffset);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
最後在onCreate方法裡再初始化一遍
initView();
initDatas();
mViewPager.setAdapter(mAdapter);
initEvent();
授人以魚不如授人以漁,這裡我就不釋出整個工程了,剩下的事情留給大家慢慢去發揮吧!