您的位置:首页 > 移动开发 > 微信开发

仿微信6.0 主界面 导航:左右滑动的ViewPager+渐变色的底部菜单

2014-11-25 23:52 501 查看
本项目 封面图:



思路:

body部分用ViewPager ,底部的图片渐变 ,可以调整两张重叠图片的透明度来实现。

1.底部的导航菜单,是自定义的一个布局。代码如下:

package com.sample.wechat.view;

import java.util.ArrayList;
import java.util.List;

import com.sample.wechat.R;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* 定制的 组件
* 描述:
* 横向排列N个条目组件
* 关联Resource:
* layout: custom_radio_button.xml
* drawable: page_indicator_focused.png
*/

@SuppressLint("NewApi") public class CustomRadioGroup extends LinearLayout{
/**
* IMAGE/TEXT : 条目的图片/文字
* START/DIF : 初始值/和目标的差值
* R/G/B : 目标颜色RGB格式下的R/G/B
*/
private static final int TEXT_START_COLOR=Color.GRAY,END_COLOR=Color.parseColor("#45c01a"),
TEXT_START_R=Color.red(TEXT_START_COLOR), TEXT_START_G=Color.green(TEXT_START_COLOR), TEXT_START_B=Color.blue(TEXT_START_COLOR),
TEXT_DIF_R=Color.red(END_COLOR)-TEXT_START_R, TEXT_DIF_G=Color.green(END_COLOR)-TEXT_START_G, TEXT_DIF_B=Color.blue(END_COLOR)-TEXT_START_B;
;
//相关的资源ID:
private final int ID_LAYOUT=R.layout.custom_radio_button,ID_IMAGE_TOP=R.id.custom_radio_button_image_top,ID_IMAGE_BOTTOM=R.id.custom_radio_button_image_botom,ID_TEXT=R.id.custom_radio_button_text,ID_NEWS=R.id.custom_radio_button_news;
//条目变更监听
private OnItemChangedListener onItemChangedListener;
//条目的LinearLayout.LayoutParams
private LayoutParams itemLayoutParams=new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
private LayoutInflater inflater;
//当前选择的条目
private int checkedIndex=0;
//条目列表
private List<RadioButton> lists=new ArrayList<CustomRadioGroup.RadioButton>();
public CustomRadioGroup(Context c) {
super(c);
init();
}
public CustomRadioGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/**
* 构造函数里适用的初始化部分
*/
private void init() {
inflater=LayoutInflater.from(getContext());
itemLayoutParams.weight=1;
setOrientation(HORIZONTAL);
}
/**
* @param f 颜色渐变参考值。
*/
private static int getNewColor(float f){
int newR,newG,newB;
newR=(int)(TEXT_DIF_R*f)+TEXT_START_R;
newG=(int)(TEXT_DIF_G*f)+TEXT_START_G;
newB=(int)(TEXT_DIF_B*f)+TEXT_START_B;
return Color.rgb(newR, newG, newB);
}
/**
* 添加条目
* @param unSelected 没有选中时的图片
* @param selected 选中时的图片
* @param text 文本内容
*/
public void addItem(int unSelected,int selected,String text){
RadioButton rb=new RadioButton(unSelected,selected,text);
final int i=lists.size();
rb.v.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
setCheckedIndex(i);
}
});
addView(rb.v);
lists.add(rb);
}
/**
* 获取选中的条目索引
*/
public int getCheckedIndex() {
return checkedIndex;
}
/**
* 两个item 改变透明度
* @param leftIndex 左边的条目索引
* @param rightIndex 右边的条目索引
* @param alpha [0,1)透明度
*/
public void itemChangeChecked(int leftIndex,int rightIndex,float alpha){
if (leftIndex<0||leftIndex>=lists.size()||rightIndex<0||rightIndex>=lists.size()) {
return ;
}
RadioButton a=lists.get(leftIndex);
RadioButton b=lists.get(rightIndex);
a.top.setAlpha(alpha);
a.bottom.setAlpha(1-alpha);
b.top.setAlpha(1-alpha);
b.bottom.setAlpha(alpha);
int aColor=getNewColor(1-alpha);
int bColor=getNewColor(alpha);
a.text.setTextColor(aColor);
b.text.setTextColor(bColor);
}
/**
* 选择制定索引的条目
*/
public void setCheckedIndex(int index) {
for (int i = 0; i < lists.size(); i++) {
if (i==index) {
lists.get(i).setCheceked(true);
lists.get(i).text.setTextColor(END_COLOR);
}else{
lists.get(i).setCheceked(false);
lists.get(i).text.setTextColor(TEXT_START_COLOR);
}
}
this.checkedIndex=index;
if (this.onItemChangedListener!=null) {
onItemChangedListener.onItemChanged();
}
}
/**
* 设置指定索引的条目的消息数量
* @param index 条目的索引
* @param count 消息的数量
*/
public void setItemNewsCount(int index,int count){
lists.get(index).setNewsCount(count);
}

/**
* 设置条目变更监听器
* @param onItemChangedListener
*/
public void setOnItemChangedListener(OnItemChangedListener onItemChangedListener) {
this.onItemChangedListener = onItemChangedListener;
}

/**
* 自定义的RadioButton
*/
private class RadioButton {
View v; //条目样式
ImageView top,bottom; //条目的图片
TextView text,news; //条目的文字,消息
public RadioButton(int unSelected,int selected,String string) {
v=inflater.inflate(ID_LAYOUT, null);
top=(ImageView)v.findViewById(ID_IMAGE_TOP);
bottom=(ImageView)v.findViewById(ID_IMAGE_BOTTOM);
text=(TextView)v.findViewById(ID_TEXT);
news=(TextView)v.findViewById(ID_NEWS);

top.setImageResource(unSelected);
top.setAlpha(1.0f);
bottom.setImageResource(selected);
bottom.setAlpha(0.0f);
text.setText(string);
news.setVisibility(INVISIBLE);
v.setLayoutParams(itemLayoutParams);
}
/**
* 设置消息数量
* @param count 消息数量为0,不显示news的TextView,消息数量>0 显示news的TextView
*/
void setCheceked(boolean b){
if (b) {
top.setAlpha(0.0f);
bottom.setAlpha(1.0f);
}else{
top.setAlpha(1.0f);
bottom.setAlpha(0.0f);
}
}

void setNewsCount(int count){
if (count<=0) {
news.setVisibility(INVISIBLE);
}else {
news.setText(count+"");
news.setVisibility(VISIBLE);
}
}
}
/**
* 条目变更监听接口
*/
public interface OnItemChangedListener{
public void onItemChanged();
}
}

它关联的图片,是一个红色的圆形,而关联的XML文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white">
<LinearLayout
android:id="@+id/custom_radio_button_main"
android:layout_width="wrap_content"
android:paddingTop="5dp"
android:layout_height="54dp"
android:layout_centerInParent="true"
android:orientation="vertical"
android:gravity="center_horizontal"
android:background="@android:color/white"
android:baselineAligned="false"
>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/custom_radio_button_image_botom"
android:contentDescription="@string/hello_world"
android:layout_width="32dp"
android:layout_height="28dp"
android:src="@drawable/ic_launcher"
android:background="@android:color/transparent"
android:scaleType="fitCenter"
/>
<ImageView
android:id="@+id/custom_radio_button_image_top"
android:contentDescription="@string/hello_world"
android:layout_width="32dp"
android:layout_height="28dp"
android:src="@drawable/ic_launcher"
android:background="@android:color/transparent"
android:scaleType="fitCenter"
/>
</FrameLayout>
<TextView
android:id="@+id/custom_radio_button_text"
android:text="@string/app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
/>
</LinearLayout>
<TextView
android:layout_alignTop="@id/custom_radio_button_main"
android:layout_toRightOf="@id/custom_radio_button_main"
android:id="@+id/custom_radio_button_news"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginTop="5dp"
android:background="@drawable/news_bg"
android:layout_marginLeft="-10dp"
android:textColor="@android:color/white"
android:gravity="center"
/>

</RelativeLayout>

2. 使用举例

 主布局为:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.sample.wechat.MainActivity" >

<com.sample.wechat.view.CustomRadioGroup
android:id="@+id/main_footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
></com.sample.wechat.v
99e8
iew.CustomRadioGroup>
<android.support.v4.view.ViewPager
android:id="@+id/main_body"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/main_footer"
></android.support.v4.view.ViewPager>
</RelativeLayout>


 Activity为:
package com.sample.wechat;

import java.util.ArrayList;
import java.util.List;

import com.sample.wechat.view.CustomRadioGroup;
import com.sample.wechat.view.CustomRadioGroup.OnItemChangedListener;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.ViewGroup;

public class MainActivity extends FragmentActivity {
private CustomRadioGroup footer;
private ViewPager body;
private int[] itemImage={R.drawable.main_footer_message,R.drawable.main_footer_contanct,R.drawable.main_footer_discovery,R.drawable.main_footer_me};
private int[] itemCheckedImage={R.drawable.main_footer_message_selected,R.drawable.main_footer_contanct_selected,R.drawable.main_footer_discovery_selected,R.drawable.main_footer_me_selected};
private String[] itemText={"微信","通讯录","发现","我"};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initContentView();
}
public void initContentView() {
// 底部
footer=(CustomRadioGroup)findViewById(R.id.main_footer);
for (int i = 0; i < itemImage.length; i++) {
footer.addItem(itemImage[i],itemCheckedImage[i],itemText[i]);
}
//主体
body=(ViewPager)findViewById(R.id.main_body);
body.setAdapter(new BodyPageAdapter());
final MainBodyPageChangeListener bodyChangeListener=new MainBodyPageChangeListener(footer);
body.setOnPageChangeListener(bodyChangeListener);

footer.setCheckedIndex(body.getCurrentItem());
footer.setOnItemChangedListener(new OnItemChangedListener() {
public void onItemChanged() {
body.setCurrentItem(footer.getCheckedIndex(),false);
}
});
/**
* BUG :显示不出数字。数字尺寸太大
*/
footer.setItemNewsCount(1, 10);//设置消息数量

}
class BodyPageAdapter extends PagerAdapter{
private int[] pageLayouts={R.layout.main_body_page_a,R.layout.main_body_page_b,R.layout.main_body_page_c,R.layout.main_body_pager_d};
private List<View> lists=new ArrayList<View>();
public BodyPageAdapter() {
for (int i = 0; i < pageLayouts.length; i++) {
View v=getLayoutInflater().inflate(pageLayouts[i], null);
lists.add(v);
}
}
public int getCount() {
return lists.size();
}

@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return arg0==arg1;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View v=lists.get(position);
container.addView(v);
return v;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(lists.get(position));
}
}

class MainBodyPageChangeListener implements OnPageChangeListener{
private CustomRadioGroup customRadioGroup;
public MainBodyPageChangeListener(CustomRadioGroup c) {
this.customRadioGroup=c;
}
public void onPageScrollStateChanged(int arg0) {
}
public void onPageScrolled(int arg0, float arg1, int arg2){
if (arg1!=0.0f) {
int right,left;
if (arg0==customRadioGroup.getCheckedIndex()) {
//方向向右
left=customRadioGroup.getCheckedIndex();
right=customRadioGroup.getCheckedIndex()+1;
}else{
//方向向左
left=customRadioGroup.getCheckedIndex()-1;
right=customRadioGroup.getCheckedIndex();

}
customRadioGroup.itemChangeChecked(left, right, arg1);
}else{
customRadioGroup.setCheckedIndex(arg0);
}
}
public void onPageSelected(int arg0){
}

}

}


部分,问题说明:

1.源码是一个Eclipse项目,使用的编码格式为UTF-8

2.设置透明度,对API的要求大于11。

源码链接:项目源代码 下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐