仿 QQ 底部 tab 导航

news/2024/12/22 9:18:47/

仿 QQ 底部 tab 导航

本篇博客主要实现以下效果:

  • 使用FragmentTabHost实现qq底部Tab切换
  • 使用RadioGroup和RadioButton实现仿qq底部切换
  • 使用RadioGroup和ViewPager 实现可以滑动切换的仿qq底部Tab切换
  • 解决Fragment多次实例化的几种方案
  • Fragemnt的懒加载(网上很多人称之为Fragemnt的最优加载)

效果图

老规矩,废话 不多说,先看效果图

FragmentTabHost实现qq底部Tab实践的效果图


RadioGroup和ViewPager 实现可以滑动切换的仿qq底部Tab效果图


使用FragmentTabHost实现qq底部Tab切换

第一步先看布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!--用来填充Fragemnt的FrayLayout--><FrameLayoutandroid:id="@+id/main_layout_content"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"></FrameLayout><!--FragmentTabHost--><android.support.v4.app.FragmentTabHostandroid:id="@android:id/tabhost"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#F6F6F6"android:paddingBottom="5dp"android:paddingTop="5dp"><FrameLayoutandroid:id="@android:id/tabcontent"android:layout_width="0dp"android:layout_height="0dp"/></android.support.v4.app.FragmentTabHost></LinearLayout>

其实很简单,没什么好说的 ,就是一个vertical的LinearLayout中放置着一个FrameLayout和FragmentTabHost

接下来我们来看一下代码

public class FirstStyleActivity extends AppCompatActivity {FragmentTabHost mTabHost;private TabWidget mTabWidget;private List<FragmentInfo> mFragmentEntities;private static final String TAG = "xujun";private static final String tag = "tag";public static final String[] mTiltles = new String[]{"首页", "课程", "直播", "个人"};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_first_style);mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);mTabHost.setup(this, getSupportFragmentManager(), R.id.main_layout_content);mTabWidget = mTabHost.getTabWidget();//  去掉分割线mTabWidget.setDividerDrawable(null);mFragmentEntities = MainFragmentFactory.getInstance().getList();initListener();initData();}private void initData() {int size = mFragmentEntities.size();for (int i = 0; i < size; i++) {Log.i(TAG, "size:=" + size);FragmentInfo fragmentInfo = mFragmentEntities.get(i);String title = fragmentInfo.getTitle();TabHost.TabSpec tabSpec = mTabHost.newTabSpec(title).setIndicator(getTabView(i));Bundle bundle = new Bundle();bundle.putString(tag, mTiltles[i]);mTabHost.addTab(tabSpec, fragmentInfo.getClz(), bundle);}updateTab(0);}private void initListener() {mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {@Overridepublic void onTabChanged(String tabId) {int currentTab = mTabHost.getCurrentTab();Log.i(TAG, "onTabChanged:currentTab:=" + currentTab);updateTab(currentTab);}});}private View getTabView(int i) {View view = View.inflate(this, R.layout.tab_layout, null);int currentTab = mTabHost.getCurrentTab();Log.i(TAG, "currentTab:=" + currentTab);setSingleView(view, currentTab, i);return view;}private void setSingleView(View view, int currentTab, int index) {FragmentInfo fragmentInfo = mFragmentEntities.get(index);int[] imagIds = fragmentInfo.getImagIds();int[] colors = fragmentInfo.getColors();TextView tv = (TextView) view.findViewById(R.id.tab_tv);ImageView iv = (ImageView) view.findViewById(R.id.tab_icon);tv.setText(fragmentInfo.getTitle());Resources resources = getResources();if (index == currentTab) {tv.setTextColor(resources.getColor(colors[1]));iv.setImageDrawable(resources.getDrawable(imagIds[1]));} else {tv.setTextColor(getResources().getColor(colors[0]));iv.setImageDrawable(resources.getDrawable(imagIds[0]));}}private void updateTab(int currentTab) {int childCount = mTabWidget.getChildCount();for (int i = 0; i < childCount; i++) {View view = mTabWidget.getChildTabViewAt(i);setSingleView(view, currentTab, i);}}
}

其实说起来也很简单,主要分为以下步骤

  • 第一步,实例化FragmentTabHost并设置相关样式
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);mTabHost.setup(this, getSupportFragmentManager(), R.id.main_layout_content);
mTabWidget = mTabHost.getTabWidget();
//  去掉分割线
mTabWidget.setDividerDrawable(null);
 for (int i = 0; i < size; i++) {Log.i(TAG, "size:=" + size);FragmentInfo fragmentInfo = mFragmentEntities.get(i);String title = fragmentInfo.getTitle();TabHost.TabSpec tabSpec = mTabHost.newTabSpec(title).setIndicator(getTabView(i));Bundle bundle = new Bundle();bundle.putString(tag, mTiltles[i]);mTabHost.addTab(tabSpec, fragmentInfo.getClz(), bundle);
}
  • 第三步,通过设置 监听器来实现底部tab颜色和图案样式的转换
 mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {@Overridepublic void onTabChanged(String tabId) {int currentTab = mTabHost.getCurrentTab();Log.i(TAG, "onTabChanged:currentTab:=" + currentTab);updateTab(currentTab);}
});

运行上述代码及可以看到如下效果图


使用RadioGroup和RadioButton实现仿qq底部切换

第一步 ,先看布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutandroid:id="@+id/activity_second_style"xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"
><!--用来填充Fragemnt的FrayLayout--><FrameLayoutandroid:id="@+id/fl"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"></FrameLayout><!--使用RadioGroup来实现tab的切换--><RadioGroupandroid:id="@+id/rg"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><RadioButtonandroid:id="@+id/rb_home"style="@style/bottom_tab"android:drawableTop="@drawable/sel_home"android:text="首页"/><RadioButtonandroid:id="@+id/rb_course"style="@style/bottom_tab"android:drawableTop="@drawable/sel_course"android:text="课程"/><RadioButtonandroid:id="@+id/rb_direct_seeding"style="@style/bottom_tab"android:drawableTop="@drawable/sel_direct_seeding"android:text="直播"/><RadioButtonandroid:id="@+id/rb_me"style="@style/bottom_tab"android:drawableTop="@drawable/sel_me"android:text="我的"/></RadioGroup></LinearLayout>

其实每一个tab的选中时利用RadioGroup中RadioButton的互相排斥的特性,即每一次只能选中一个 RadioButton

至于bottom_tab的style,只不过是将相同的arr提取出来,减少布局的代码量和方便统一修改而已,平时我们在写布局代码 的时候也可以这样

<style name="bottom_tab"><item name="android:layout_width" >0dp</item><item name="android:layout_height" >wrap_content</item><item name="android:layout_weight" >1</item><item name="android:text" >0dp</item><item name="android:gravity" >center</item><item name="android:textColor" >@drawable/sel_bottom_tab_text</item><item name="android:padding" >8dp</item><item name="android:button" >@null</item>
</style>

第二步,我们来看一下Activity的 代码

public class ThreeActivity extends AppCompatActivity {FrameLayout mFl;RadioGroup mRg;private FragmentManager mFragmentManager;private int position = 0;public static final String[] mTiltles = new String[]{"首页", "课程", "直播", "个人"};private List<Fragment> mFragments;private Fragment mCurFragment;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_three);mFl = (FrameLayout) findViewById(R.id.fl);mRg = (RadioGroup) findViewById(R.id.rg);mFragments = new ArrayList<>();for (int i = 0; i < mTiltles.length; i++) {ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);mFragments.add(itemFragement);}mCurFragment = mFragments.get(position);replaceFragment(mCurFragment);((RadioButton)mRg.getChildAt(position)).setChecked(true);initListener();}private void initListener() {mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {RadioButton radioButton = (RadioButton) group.findViewById(checkedId);if (false == radioButton.isChecked()) {return;}switch (checkedId) {case R.id.rb_home:position = 0;break;case R.id.rb_course:position = 1;break;case R.id.rb_direct_seeding:position = 2;break;case R.id.rb_me:position = 3;break;default:position = 0;break;}LUtils.i("position==" + position);Fragment to = mFragments.get(position);showFragment(mCurFragment, to);mCurFragment = to;}});}private void showFragment(Fragment from, Fragment to) {FragmentManager supportFragmentManager = getSupportFragmentManager();FragmentTransaction transaction = supportFragmentManager.beginTransaction();if (!to.isAdded()) {    // 先判断是否被add过transaction.hide(from).add(R.id.fl, to).commit(); // 隐藏当前的fragment,add下一个到Activity中} else {transaction.hide(from).show(to).commit(); // 隐藏当前的fragment,显示下一个}}/*** 这个方法用老替换fragment* xujun* 2016/5/3 17:28.*/private void replaceFragment(Fragment fragmeny) {FragmentManager supportFragmentManager = getSupportFragmentManager();FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();fragmentTransaction.replace(R.id.fl, fragmeny).commit();}}

思路解析

  • 实例化各个控件,这里代码就不贴出来了
  • 初始化 Fragemnt 和选中各个tab
 mFragments = new ArrayList<>();
for (int i = 0; i < mTiltles.length; i++) {ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);mFragments.add(itemFragement);
}
mCurFragment = mFragments.get(position);
replaceFragment(mCurFragment);((RadioButton)mRg.getChildAt(position)).setChecked(true);private void replaceFragment(Fragment fragmeny) {FragmentManager supportFragmentManager = getSupportFragmentManager();FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();fragmentTransaction.replace(R.id.fl, fragmeny).commit();
}
  • 第三步,通过监听RadioGroup的 OnCheckedChangeListener事件,来实现tab和Fragemnt的切换
 mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {RadioButton radioButton = (RadioButton) group.findViewById(checkedId);if (false == radioButton.isChecked()) {return;}switch (checkedId) {case R.id.rb_home:position = 0;break;case R.id.rb_course:position = 1;break;case R.id.rb_direct_seeding:position = 2;break;case R.id.rb_me:position = 3;break;default:position = 0;break;}LUtils.i("position==" + position);Fragment to = mFragments.get(position);showFragment(mCurFragment, to);mCurFragment = to;}});

使用RadioGroup和ViewPager 实现可以滑动切换的仿qq底部Tab切换

第一步,我们 同样先看布局代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutandroid:id="@+id/activity_second_style"xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"
><!--用来填充Fragemnt的ViewPager--><android.support.v4.view.ViewPagerandroid:id="@+id/viewPager"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"></android.support.v4.view.ViewPager><!--使用RadioGroup来实现tab的切换--><RadioGroupandroid:id="@+id/rg"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><RadioButtonandroid:id="@+id/rb_home"style="@style/bottom_tab"android:drawableTop="@drawable/sel_home"android:text="首页"/><RadioButtonandroid:id="@+id/rb_course"style="@style/bottom_tab"android:drawableTop="@drawable/sel_course"android:text="课程"/><RadioButtonandroid:id="@+id/rb_direct_seeding"style="@style/bottom_tab"android:drawableTop="@drawable/sel_direct_seeding"android:text="直播"/><RadioButtonandroid:id="@+id/rb_me"style="@style/bottom_tab"android:drawableTop="@drawable/sel_me"android:text="我的"/></RadioGroup></LinearLayout>

第二步,我们一起来看一下Activity代码

public class SecondStyleActivity extends AppCompatActivity {public static final String[] mTiltles = new String[]{"首页", "课程", "直播", "个人"};private List<Fragment> mFragments;ViewPager mViewPager;RadioGroup mRg;private int position = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second_style);mViewPager = (ViewPager) findViewById(R.id.viewPager);mRg = (RadioGroup) findViewById(R.id.rg);initListener();initData();}private void initData() {mFragments = new ArrayList<>();for (int i = 0; i < mTiltles.length; i++) {ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);mFragments.add(itemFragement);}BaseFragmentAdapter fragmentAdapter = new BaseFragmentAdapter(getSupportFragmentManager(), mFragments, mTiltles);mViewPager.setAdapter(fragmentAdapter);mViewPager.setCurrentItem(position);((RadioButton) mRg.getChildAt(position)).setChecked(true);}private void initListener() {mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {@Overridepublic void onPageSelected(int position) {RadioButton radioButton = (RadioButton) mRg.getChildAt(position);radioButton.setChecked(true);}});mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {RadioButton rb = (RadioButton) group.findViewById(checkedId);if (!rb.isChecked()) {return;}switch (checkedId) {case R.id.rb_home:position = 0;break;case R.id.rb_course:position = 1;break;case R.id.rb_direct_seeding:position = 2;break;case R.id.rb_me:position = 3;break;default:position = 0;break;}mViewPager.setCurrentItem(position);}});}
}

思路解析如下

 mViewPager = (ViewPager) findViewById(R.id.viewPager);mRg = (RadioGroup) findViewById(R.id.rg);
  • 第二步,初始化ViewPager的适配器和选中 那个tab
 mFragments = new ArrayList<>();
for (int i = 0; i < mTiltles.length; i++) {ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);mFragments.add(itemFragement);
}
BaseFragmentAdapter fragmentAdapter = new BaseFragmentAdapter(getSupportFragmentManager(), mFragments, mTiltles);
mViewPager.setAdapter(fragmentAdapter);
mViewPager.setCurrentItem(position);
((RadioButton) mRg.getChildAt(position)).setChecked(true);
  • 第三步,监听ViewPager 的滑动事件和RadioGroup的OnCheckedChangeListener事件,分别切换到相应的 Fragemnt 和同步ViewPager中 position 与RadioGroup之间的联系
 mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {@Overridepublic void onPageSelected(int position) {RadioButton radioButton = (RadioButton) mRg.getChildAt(position);radioButton.setChecked(true);}
});mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {RadioButton rb = (RadioButton) group.findViewById(checkedId);if (!rb.isChecked()) {return;}switch (checkedId) {case R.id.rb_home:position = 0;break;case R.id.rb_course:position = 1;break;case R.id.rb_direct_seeding:position = 2;break;case R.id.rb_me:position = 3;break;default:position = 0;break;}mViewPager.setCurrentItem(position);}
});

注意事项

我们可以通过以下方法设置ViewPager左右页面 能缓存的fragment 数量

//  设置左右页面 能缓存的fragment 数量
mViewPager.setOffscreenPageLimit(fragmentAdapter.getCount() - 1);

到此仿qq底部tab切换的集中方法已经讲解完毕,之所以讲解了 三种方法,是想让大家了解多种实现方式,因为每一个人的习惯bout不一样,有些人习惯使用与第一种方式,有人习惯使用第二种方式。。。了解多种 实现方式以后,我们 要读懂别人 的代码也容易得多了,其实我们还可以使用自定义控件来实现,方法也比较简单,这里就不讲解了,有兴趣的话,可以去 阅读 这篇博客

下面我将为大家讲解Fragment的 一些优化

解决Fragment多次实例化的几种方案

目前本人了解到的解决方案 ,无非是利用一下两种思想

第一种解决方法

在onCreateView中避免多次实例化View,可通过判断View是否为空,来实现相应的 逻辑操作,核心代码如下

   public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @NullableBundle savedInstanceState) {LUtils.i(getClass().getSimpleName()+">>>>>>>>>>>  onCreateView");if(mView==null){mContext = getContext();mView=View.inflate(mContext,getLayoutId(),null);initView(mView);LUtils.i(getClass().getSimpleName()+">>>>>>>>>>>  initView");}else{// 缓存的rootView需要判断是否已经被加过parent,如果有parent需要从parent删除,// 要不然会发生这个rootview已经有parent的错误。ViewGroup parent =(ViewGroup) mView.getParent();if(parent!=null){parent.removeView(mView);}LUtils.i(getClass().getSimpleName()+">>>>>>>>>>>  removeView");}return mView;}

第二种解决方案

在项目中需要进行Fragment的切换,用hide()和show()方法结合起来来替代replace()方法来实现Fragment的切换:

private void showFragment(Fragment from, Fragment to) {FragmentManager supportFragmentManager = getSupportFragmentManager();FragmentTransaction transaction = supportFragmentManager.beginTransaction();if (!to.isAdded()) {    // 先判断是否被add过transaction.hide(from).add(R.id.fl, to).commit(); // 隐藏当前的fragment,add下一个到Activity中} else {transaction.hide(from).show(to).commit(); // 隐藏当前的fragment,显示下一个}}/*** 这个方法用老替换fragment* xujun* 2016/5/3 17:28.*/private void replaceFragment(Fragment fragmeny) {FragmentManager supportFragmentManager = getSupportFragmentManager();FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();fragmentTransaction.replace(R.id.fl, fragmeny).commit();
}

关于 避免Fragment的多次实例化的分析与优化到此为止,下面我们一起来看一下 则那样实现Fragemnt 的 懒加载

Fragemnt的懒加载(网上很多人称之为Fragemnt的最优加载)

关于懒加载的这部分,代码是参考这篇 博客的 ViewPager+Fragment LazyLoad最优解

我们知道 ViewPager通常 会有预加载机制,默认情况下会先加载左右一页的数据,有时候我们想等待页面可见的时候在去加载网络 数据 ,解决方案如下

下面 先贴出代码

public abstract class BasePageFragment extends Fragment {protected View mView;/*** 表示View是否被初始化*/protected boolean isViewInitiated;/*** 表示对用户是否可见*/protected boolean isVisibleToUser;/*** 表示数据是否初始化*/protected boolean isDataInitiated;private Context mContext;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onCreate");}@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @NullableBundle savedInstanceState) {LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onCreateView");if (mView == null) {mContext = getContext();mView = View.inflate(mContext, getLayoutId(), null);initView(mView);LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  initView");} else {// 缓存的rootView需要判断是否已经被加过parent,如果有parent需要从parent删除,// 要不然会发生这个rootview已经有parent的错误。ViewGroup parent = (ViewGroup) mView.getParent();if (parent != null) {parent.removeView(mView);}LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  removeView");}return mView;}protected abstract void initView(View view);protected abstract int getLayoutId();@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onActivityCreated");isViewInitiated = true;initData();prepareFetchData();}@Overridepublic void setUserVisibleHint(boolean isVisibleToUser) {super.setUserVisibleHint(isVisibleToUser);this.isVisibleToUser = isVisibleToUser;prepareFetchData();}public abstract void fetchData();public boolean prepareFetchData() {return prepareFetchData(false);}/**** * @param forceUpdate 表示是否在界面可见的时候是否强制刷新数据* @return*/public boolean prepareFetchData(boolean forceUpdate) {if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {//  界面可见的时候再去加载数据fetchData();isDataInitiated = true;return true;}return false;}@Overridepublic void onDestroyView() {super.onDestroyView();LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onDestroyView");}protected void initData() {}}

思路解析:
其实核心思想主要在setUserVisibleHint(boolean isVisibleToUser)方法中,这个方法在Fragemnt界面切换到可见或者 不可见的时候调用,isVisibleToUser表示当前界面可见 或者不可见

setUserVisibleHint(boolean isVisibleToUser)

Set a hint to the system about whether this fragment's UI is currently visible to the user.

于是我们在prepareFetchData进行判断只有当界面可见的情况下才会尝试判断是否调用fetchData() 方法,于是我们就可以实现等到界面可见的 时候才加载网络数据,将我们加载网络数据的 逻辑的实现放在fetchData()
里面即可

/***** @param forceUpdate 表示是否在界面可见的时候是否强制刷新数据* @return*/
public boolean prepareFetchData(boolean forceUpdate) {if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {//  界面可见的时候再去加载数据fetchData();isDataInitiated = true;return true;}return false;
}

转载请注明博客地址:http://blog.csdn.net/gdutxiaoxu/article/details/52826810

源码下载地址:https://github.com/gdutxiaoxu/QQBottomTab.git


http://www.ppmy.cn/news/363631.html

相关文章

网站QQ导航

<a href"http://wpa.qq.com/msgrd?v3&uin[colorRed]361983679[/color]&siteqq&menuyes" target"_blank"><img border"0" title"单击联系站长苏飞" alt"单击联系站长苏飞" src"http://wpa.qq.com…

自己写的仿QQ空间导航栏

<!doctype html> <html> <head> <meta charset"utf-8"> <title>无标题文档</title> <style type"text/css"> *{ margin:0; padding:0; } .wrap{ width:900px; padding:0; margin:0 auto; border:1px solid #999…

32、用html制作QQ会员页面导航(半成品,需要素材)

<!DOCTYPE html> <html><head><meta charset"utf-8"><title>制作QQ会员页面导航</title><style type"text/css">*{margin: 0px auto;padding: 0px;}div{margin: 10px;color: white;width: 100%;height: 50px;ba…

仿qq底部Tab导航

本篇博客主要实现以下效果&#xff1a; 使用FragmentTabHost实现qq底部Tab切换使用RadioGroup和RadioButton实现仿qq底部切换使用RadioGroup和ViewPager 实现可以滑动切换的仿qq底部Tab切换解决Fragment多次实例化的几种方案Fragemnt的懒加载&#xff08;网上很多人称之为Frag…

一个仿QQ导航菜单,非常实用!

<html><head><meta http-equiv"Content-Type" content"text/html; charsetgb2312"><title>仿QQ导航菜单</title><style type"text/css">.titleStyle{background-color:#008800;color:#ffffff;border-top:1p…

web制作QQ会员导航

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>QQ会员-不做大多数</title> <link rel"icon" href"img/logo.png" type"x-png" /><style>li {list-…

最新QQ空间免费导航代码

最新QQ空间免费导航代码(超漂亮) javascript:window.top.space_addItem(13,5503,0,0,600,200,0); qq空间免费导航代码 - 横向的花藤 javascript:window.top.space_addItem(13,5503,0,0,600,200,0); qq空间免费导航代码-五星 javascript:window.top.space_addItem(13,5145,0,…

基于qq.maps.com的web地图定位导航

<!DOCTYPE html> <html> <meta charset"GBK"> <head> <meta name"viewport" content"widthdevice-width, initial-scale1.0, minimum-scale1.0, maximum-scale1.0, user-scalableno"/> <title>根据起终点经…