关注公众号“码农帮派”,查看更多系列技术文章:
首先是模仿效果:
项目模仿了手Q空间首页,主要是实现了一个可以随着ListView的滑动,逐渐改变自身Alpha数值的TopBar。
使用了View自定义属性,首先需要在res/values/attrs.xml中声明新属性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TopBar">
<attr name="titleTextColor" format="color"/>
<attr name="titleTextSize" format="dimension"/>
<attr name="titleText" format="string"/>
</declare-styleable>
</resources>
TopBar的布局文件(res/layout/activity_main.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/relative_main_bottom"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="-1dp"
android:layout_marginLeft="-1dp"
android:layout_marginRight="-1dp"
android:background="@drawable/shape_bottom"
android:gravity="center_vertical"
android:orientation="horizontal"
>
<Button
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginRight="4dp"
android:layout_weight="1"
android:background="@drawable/shape_qqphone"
android:gravity="center"
android:text="QQ电话"
android:textColor="@color/blue_app"
android:textSize="16dp"
/>
<Button
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="4dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:background="@drawable/shape_sendmsg"
android:gravity="center"
android:text="发消息"
android:textColor="@color/white"
android:textSize="16dp"
/>
</LinearLayout>
<ListView
android:id="@+id/listView_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/relative_main_bottom"
android:layout_marginBottom="13dp"
android:divider="@color/white"
android:dividerHeight="0dp"
/>
<com.tencent.alphatopbar.TopBar
android:id="@+id/topBar_main"
android:layout_width="match_parent"
android:layout_height="@dimen/mTopbatTargetOffset"
android:background="@color/colorPrimary"
app:titleText="个人资料"
app:titleTextColor="@color/white"
app:titleTextSize="17dp"
>
<LinearLayout
android:id="@+id/line_main_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:gravity="center_vertical"
android:orientation="horizontal"
>
<ImageView
android:layout_width="23dp"
android:layout_height="23dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="9dp"
android:background="@drawable/back_bg_icon"
/>
<TextView
android:id="@+id/tv_main_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="返回"
android:textColor="@color/white"
android:textSize="15dp"
/>
</LinearLayout>
</com.tencent.alphatopbar.TopBar>
</RelativeLayout>
[注意]
以为TopBar继承了RelativeLayout,因此可以像RelativeLayout一样布局内部控件。
下面是最重要的部分,TopBar的实现:
package com.tencent.alphatopbar;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* Created by maxiaodong on 16/8/3.
*/
public class TopBar extends RelativeLayout
{
Paint mPaint = null;
private String titleText = "";
private int titleTextColor = 0x000000;
private int titleTextSize = 12;
Rect mBounds;
public TopBar(Context context)
{
super(context);
}
public TopBar(Context context, AttributeSet attrs)
{
super(context, attrs);
init(context, attrs);
}
public TopBar(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs)
{
mPaint = new Paint();
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.TopBar);
titleText = array.getString(R.styleable.TopBar_titleText);
if (TextUtils.isEmpty(titleText))
{
titleText = "";
}
titleTextColor = array.getColor(R.styleable.TopBar_titleTextColor, Color.BLACK);
titleTextSize = array.getDimensionPixelSize(R.styleable.TopBar_titleTextSize, 12);
array.recycle();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBounds = new Rect();
mPaint.setColor(titleTextColor);
mPaint.setTextSize(titleTextSize);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
mPaint.getTextBounds(titleText, 0, titleText.length(), mBounds);
float textWidth = mBounds.width();
float textHeight = mBounds.height();
canvas.drawText(titleText, getWidth() / 2 - textWidth / 2, getHeight() / 2
+ textHeight / 2, mPaint);
}
/**
* 修改TopBar背景的透明度
*
* @alpha 透明度 取值范围在[0, 255]
*/
public void setBackgroundAlpha(int alpha)
{
this.getBackground().setAlpha(alpha);
}
/***
* 计算TopBar当前的透明度
*
* @param currentOffset
* @param alphaTargetOffset currentOffset == alphaTargetOffset时,透明度为1
*/
public void computeAndsetBackgroundAlpha(int currentOffset, int alphaTargetOffset)
{
float alpha = currentOffset * 1.0f / alphaTargetOffset;
alpha = Math.max(0, Math.min(alpha, 1));
int alphaInt = (int) (alpha * 255);
this.setBackgroundAlpha(alphaInt);
}
}
最后要在MainActivity.java中,将ListView的滑动和TopBar绑定在一起,这样才能实现TopBar背景的渐变:
listView_main.setOnScrollListener(new AbsListView.OnScrollListener()
{
@Override
public void onScrollStateChanged(AbsListView absListView, int i)
{
}
@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2)
{
topBar_main.computeAndsetBackgroundAlpha(getScrollY() / 1, mTopbatTargetOffset);
}
});
注意:因为项目中使用到了v7中的RecycleView,所以需要引入(app/build.gradle):
compile "com.android.support:recyclerview-v7:${supportLibVersion}"
当然此处也可以使用Android的画廊布局gallery,但是gallery已经被抛弃。
完整的项目下载(代码比较乱,仅提供TopBar渐变的参考):
https://github.com/BaijiaDong/-Q-.git