当前位置: 代码迷 >> Android >> Android 学习 之 仿照人人底部导航条
  详细解决方案

Android 学习 之 仿照人人底部导航条

热度:308   发布时间:2016-05-01 18:57:29.0
Android 学习 之 模仿人人底部导航条

截图见附件:

?

先准备几张图片吧,在附件那里:(注意:倒数第二张图片附件是个9文件,下载完了记得把后缀改成.9.png)

?

1.新建一个工程,爱叫什么名随便哈,这不是重点。

?

我的工程中把main.xml改成了tabmain.xml,因为我的Activity叫TabMain。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/container_frame">

<!-- android:scrollbarThumbHorizontal="@drawable/scrollbar" -->
<!-- android:scrollbarAlwaysDrawHorizontalTrack="false" -->
<!-- android:scrollbarStyle="outsideOverlay" -->
<!-- android:fadingEdge="horizontal" -->
<!-- android:fadingEdgeLength="5.0dip" -->

<HorizontalScrollView
android:scrollbars="none"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@drawable/horizontal_bg"
android:id="@+id/container_horizontal">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="@dimen/horizontal_height">
</LinearLayout>
</HorizontalScrollView>
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="@dimen/horizontal_height"
android:id="@+id/container_relative">
<ImageButton
android:id="@+id/left_image"
android:layout_alignParentLeft="true"
android:visibility="gone"
android:layout_width="@dimen/imagebutton_width"
android:layout_height="fill_parent"
android:background="@drawable/arrowl" />
<ImageButton
android:id="@+id/right_image"
android:layout_alignParentRight="true"
android:visibility="gone"
android:layout_width="@dimen/imagebutton_width"
android:layout_height="fill_parent"
android:background="@drawable/arrowr" />
</RelativeLayout>

</FrameLayout>

?

?

2.修改AndroidManifest.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ql.app"
android:versionCode="1"
android:versionName="1.0">

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".TabMain"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden|navigation" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>

<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" ></uses-permission>
</manifest>

?

3.在res/values文件夹下新建一个xml文件,attrs.xml

?

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="custom">
<attr name="arrayId" format="reference" />
</declare-styleable>
</resources>

同样的,新建一个deimens.xml文件

?

<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="horizontal_height">50dip</dimen>
<dimen name="textview_width">120dip</dimen>
<dimen name="textview_size_big">25sp</dimen>
<dimen name="textview_size_small">20sp</dimen>
<dimen name="imagebutton_width">25dip</dimen>
</resources>

3.重点来了,这个是TabMain.java

?

package com.ql.app;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.HorizontalScrollView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.LinearLayout.LayoutParams;

public class TabMain extends Activity{

/**
* 水平滚动容器,内含一个LinearLayout,所有的子控件都在该LinearLayout容器中
* ,因此,获取子控件的时候应该先通过horizontalScrollView.getChildAt(0)获取
* 到该LinearLayout,然后再通过该LinearLayout的getChildAt()方法获取。
*/
private HorizontalScrollView horizontalScrollView;

/**
* horizontalScrollView的唯一子控件容器
*/
private LinearLayout horizontalLinearLayout;

/**
* 左边的箭头控件
*/
private ImageButton leftImage;

/**
* 右边的箭头控件
*/
private ImageButton rightImage;

/**
* 屏幕的宽度值
*/
private int mScreenW;

/**
* horizontalLinearLayout容纳文本控件的总长度
*/
private int mMeasuredW;

/**
* 文本控件字体大小值:大字体
*/
private int textSizeBig;

/**
* 文本控件字体大小值:小字体
*/
private int textSizeSmall;

/**
* 初始化时将被选中的标题索引值
*/
private int mSelectPosition = 3;

/**
* 标题内容数组
*/
// private String[] titleArrays = {"访客"};
// private String[] titleArrays = {"访客","新鲜事"};
// private String[] titleArrays = {"访客","新鲜事","资料"};
private String[] titleArrays = {"访客","新鲜事","资料","留言板","相册","日记","状态","分享","收藏"};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

if (mSelectPosition < 0) {
throw new ArrayIndexOutOfBoundsException("初始化被选中的标题索引值mSelectPosition不能小于0");
} else if (mSelectPosition >= titleArrays.length) {
throw new ArrayIndexOutOfBoundsException("初始化被选中的标题索引值mSelectPosition不能大于或等于标题总个数");
}

setContentView(R.layout.tabmain);
init();

}

/**
* 初始化
*/
private void init(){
Resources res = getResources();

textSizeBig = (int) res.getDimension(R.dimen.textview_size_big);
textSizeSmall = (int) res.getDimension(R.dimen.textview_size_small);

int textWidth = 0;

mScreenW = getResources().getDisplayMetrics().widthPixels;

horizontalScrollView = (HorizontalScrollView) findViewById(R.id.container_horizontal);
horizontalLinearLayout = (LinearLayout) horizontalScrollView.getChildAt(0);

leftImage = (ImageButton) findViewById(R.id.left_image);
rightImage = (ImageButton) findViewById(R.id.right_image);

int titleLength = titleArrays.length;

// 注意,水平滚动容器中的LinearLayout与普通的LinearLayout不一样
// 我们只能手动配置params的宽度值才能有效果,设置成FILL_PARENt或
// 比例params.weight也不起任何作用,效果都是WRAP_CONTENT。
LayoutParams params = null;

// 对标题长度进行判断,手动设置文本控件的宽度值
switch (titleLength) {
case 1:
textWidth = mScreenW;
break;
case 2:
textWidth = mScreenW >> 1;
break;
case 3:
textWidth = mScreenW / 3;
break;
default:// 当标题数组的长度大于3个的时候才它设置监听
textWidth = (int) res.getDimension(R.dimen.textview_width);
horizontalScrollView.setOnTouchListener(onTouchListener);
break;
}

params = new LinearLayout.LayoutParams(textWidth, LayoutParams.FILL_PARENT);

for (int i = 0; i < titleLength; i++) {
TextView textView = new TextView(this);
textView.setText(titleArrays[i]);
textView.setTextColor(Color.parseColor("#aaaaaa"));

if (i == mSelectPosition) {

// 设置被选中的这个文本控件给horizontalLinearLayout
horizontalLinearLayout.setTag(textView);
textView.setTextColor(Color.parseColor("#ffffff"));
textView.setBackgroundResource(R.drawable.tab_select);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeBig);

} else {

textView.setTextColor(Color.parseColor("#aaaaaa"));
textView.setBackgroundDrawable(new BitmapDrawable());
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeSmall);

}

textView.setOnClickListener(clickListener);
textView.setGravity(Gravity.CENTER);
horizontalLinearLayout.addView(textView,params);
}

// 当标题数组的长度小于3的时候,每个文本控件都是平铺在屏幕上的
// 只有大于3的时候,进行初始化操作时,才去判断是否要显示箭头
if (titleLength > 3) {

mMeasuredW = titleArrays.length * textWidth;

// 为了判断初始化被选中的文本控件的中心位置是否超过了半个屏幕
int tempInitScrollValue = (int) ((mSelectPosition + 0.5 ) * textWidth) - mScreenW/2;
Log.d("debug", "tempMeasuredW = "+mMeasuredW);

if (mMeasuredW > mScreenW) {
rightImage.setVisibility(View.VISIBLE);
}

if (tempInitScrollValue > 0) {
leftImage.setVisibility(View.VISIBLE);

// 发送消息让horizontalScrollView滚动
Message msg = new Message();
msg.what = 1;
msg.obj = String.valueOf(tempInitScrollValue);
handler.sendMessageDelayed(msg, 200);
}

}
}

private View.OnTouchListener onTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {

switch (event.getAction()) {

// 抬起的时候发送消息去判断是否要显示箭头
case MotionEvent.ACTION_UP:
if(v != null){
handler.sendEmptyMessageDelayed(0, 500);
}
break;
}
return false;
}
};

private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 0:

Rect localRect = new Rect();
horizontalScrollView.getLocalVisibleRect(localRect);
Log.d("debug", "horizontalScrollView`s Rect2 > l:"+localRect.left+" , r:"+localRect.right+
" W:"+horizontalLinearLayout.getMeasuredWidth());

// 滑动的x值
int tempScrollX = horizontalScrollView.getScrollX();
Log.d("debug", "scrollX = "+tempScrollX);

// 判断是不是达到了最左边或最右边
if (localRect.left == 0 || tempScrollX == 0) {// 最左边
// 隐藏左箭头框
leftImage.setVisibility(View.GONE);
} else {
leftImage.setVisibility(View.VISIBLE);
}

if (localRect.right == mMeasuredW || tempScrollX == mMeasuredW - mScreenW) {// 最右边
// 隐藏右箭头框
rightImage.setVisibility(View.GONE);
} else {
rightImage.setVisibility(View.VISIBLE);
}

break;

case 1:
horizontalScrollView.smoothScrollBy(Integer.parseInt((String)msg.obj), 0);
break;

}



};
};

OnClickListener clickListener = new OnClickListener() {

@Override
public void onClick(View v) {
// 点击的时候,从horizontalLinearLayout中获取未点击前那个
// 被选中的文本控件对象,并变换其颜色,背景,字体大小
TextView beforeView = (TextView) horizontalLinearLayout.getTag();
beforeView.setTextColor(Color.parseColor("#aaaaaa"));
beforeView.setBackgroundDrawable(new BitmapDrawable());
beforeView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeSmall);

// 变换被点击文本控件的颜色,背景,字体大小
TextView clickTextView = ((TextView)v);
clickTextView.setTextColor(Color.parseColor("#ffffff"));
clickTextView.setBackgroundResource(R.drawable.tab_select);
clickTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeBig);

// 把当前被点击的文本控件设置给horizontalLinearLayout
horizontalLinearLayout.setTag(clickTextView);

// 当标题控件个数大于3的时候才去判断滚动与否
if (titleArrays.length > 3) {
scroll(v);
}

}
};

private void scroll(View v){
Rect vRect = new Rect();
v.getLocalVisibleRect(vRect);
// Log.d("debug", "Click View`s vRect > l:"+vRect.left+" , t:"+vRect.top+" , r:"+vRect.right+" , b:"+vRect.bottom);

int[] hScreen = new int[2];
v.getLocationOnScreen(hScreen);
// Log.d("debug", "Click View`s hScreen = ("+hScreen[0]+" , "+hScreen[1]+")");

/*int[] hWindow = new int[2];
v.getLocationInWindow(hWindow);
Log.d("debug", "Click View`s hWindow = ("+hWindow[0]+" , "+hWindow[1]+")");

Rect localRect = new Rect();
horizontalScrollView.getLocalVisibleRect(localRect);
Log.d("debug", "horizontalScrollView`s Rect > l:"+localRect.left+" , t:"+localRect.top
+" , r:"+localRect.right+" , b:"+localRect.bottom);*/

int tempScreenW = getResources().getDisplayMetrics().widthPixels;
int viewW = v.getWidth();

// Log.d("debug", "onClick >> tempScreenW = "+tempScreenW+" viewW = "+viewW);
int scrollValue = 0;
if (vRect.left > 0 && vRect.right == viewW) {

scrollValue = -((tempScreenW-viewW)/2+vRect.left);
// Log.d("debug", "左入 >> scrollValue = "+scrollValue);

} else if ((vRect.left == 0 && vRect.right == viewW)
|| (vRect.left == 0 && vRect.right < viewW)) {

scrollValue = hScreen[0] + viewW/2 -tempScreenW/2;
// Log.d("debug", "屏显,右入 >> scrollValue = "+scrollValue);

}

Message msg = new Message();
msg.what = 1;
msg.obj = String.valueOf(scrollValue);
handler.sendMessageDelayed(msg, 300);
handler.sendEmptyMessageDelayed(0, 500);
}

public void onConfigurationChanged(android.content.res.Configuration newConfig) {
Log.d("debug", "onConfigurationChanged");
switch (newConfig.orientation) {
// 纵向
case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
Log.d("debug", "------------------ >> 纵向");
break;

// 横向
case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
Log.d("debug", "------------------ >> 横向");
break;
}
super.onConfigurationChanged(newConfig);
}

}

?

5.好了,大功告成。运行看效果吧 o(∩_∩)o

1 楼 ldci3gandroid 2011-09-27  
竟然没有人评论,真是伤心~
2 楼 kooqianfeng 2011-09-28  

我来评价一下
杯具的小男人!!!
3 楼 ldci3gandroid 2011-09-28  
kooqianfeng 写道

我来评价一下
杯具的小男人!!!

靠,你个贱人,怎么哪都有你的份捏
4 楼 2006her 2011-12-22  
不错,感谢分享哈。
5 楼 ldci3gandroid 2011-12-22  
textWidth
2006her 写道
不错,感谢分享哈。

哈哈 不客气
6 楼 jxr105 2011-12-28  
希望源码作为附件上传。
7 楼 jxr105 2011-12-28  
希望源码作为附件上传。
8 楼 jxr105 2012-01-04  
里面的"SelectPosition"一直没变?
  相关解决方案