热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

android自定义动态滚动tab+viewpager+fragment

近来一段时间,项目有点空闲,就总结总结开发中常用的东西,封装封装,提炼提炼,写写博客与大家共勉,有什么不对的或者更好的思路欢迎大家广开言路~~在android开发中,常见的ui框架中,很经典的一种就

近来一段时间,项目有点空闲,就总结总结开发中常用的东西,封装封装,提炼提炼,写写博客与大家共勉,有什么不对的或者更好的思路欢迎大家广开言路~~

 

在android开发中,常见的ui框架中,很经典的一种就是如图所示:

 

整体是自定义的支持水平滚动的tab+左右滑动viewpager+fragment

入口activity  HorizontalScrollViewTestActivity:

package com.example.webservice.widget.ColumnHorizontalScrollView;

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

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.example.webservice.R;
import com.example.webservice.bean.TabCode;
import com.example.webservice.widget.scrollTab.ScrollTabs;
/**
* 用来测试水平滚动的tab的实例activity
* @author xhf
*
*/
public class HorizontalScrollViewTestActivity extends FragmentActivity{

private ViewPager mViewPager;

/** 自定义HorizontalScrollView */
private ColumnHorizontalScrollView mColumnHorizontalScrollView;
/**
* 用来添加tab的root布局
*/
LinearLayout mRadioGroup_content;

RelativeLayout rl_column;

/** 左阴影部分*/
public ImageView shade_left;

/** 右阴影部分 */
public ImageView shade_right;

/** 屏幕宽度 */
private int mScreenWidth = 0;

private ScrollTabs stTabs;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.view_column_horizontal_scroll);
initView();

}

private void initView()
{
mColumnHorizOntalScrollView= (ColumnHorizontalScrollView)findViewById(R.id.mColumnHorizontalScrollView);

rl_column = (RelativeLayout) findViewById(R.id.rl_column);
mViewPager = (ViewPager) findViewById(R.id.viewPager);
//viewpager每次显示出来一个fragment时,都会把旁边的一个页面也预加载了,当然你可以控制预加载的页面的数量
mViewPager.setOffscreenPageLimit(0);//不预加载
shade_left = (ImageView) findViewById(R.id.shade_left);
shade_right = (ImageView) findViewById(R.id.shade_right);

stTabs = (ScrollTabs) findViewById(R.id.st_tabs);
mColumnHorizontalScrollView.setParam(this, mScreenWidth, stTabs, shade_left, shade_right, rl_column);
List lists=new ArrayList();
TabCode tc1=new TabCode(1000,"科技");
TabCode tc2=new TabCode(1001,"财经");
TabCode tc3=new TabCode(1002,"新闻");
TabCode tc4=new TabCode(1003,"原创");
TabCode tc5=new TabCode(1004,"体育");
lists.add(tc1);
lists.add(tc2);
lists.add(tc3);
lists.add(tc4);
lists.add(tc5);

//将activity传递到自定义view中,以获取screenWidth
stTabs.setParams(HorizontalScrollViewTestActivity.this,lists);
//tab item点击事件
stTabs.setOnItemClickListener(new ScrollTabs.OnItemClickListener() {        @Override        public void onItemClick(int index,TabCode tc) {            //重写底部的数据值            //envMOnitorInfo= sysLoadMonitorInfos.get(index);            //loadStatisticsData(envMonitorInfo.getStatisticsData(), showDataType);           Toast.makeText(HorizontalScrollViewTestActivity.this, String.valueOf(tc.getCode()), Toast.LENGTH_LONG).show();        }    });        List fragments=new ArrayList();    for(int i=0;i


activity布局文件view_column_horizontal_scroll:

    xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:background="@color/tx_gray1"
android:orientation="vertical" >

android:id="@+id/rl_column"
android:layout_
android:layout_
android:layout_weight="1.0" >

android:id="@+id/mColumnHorizontalScrollView"
android:layout_
android:layout_
android:scrollbars="none">

android:id="@+id/st_tabs"
android:layout_
android:layout_
android:layout_marginLeft="@dimen/dip15"
android:layout_marginRight="@dimen/dip15"
android:background="@android:color/transparent"
android:orientation="vertical" >



android:id="@+id/shade_left"
android:layout_
android:layout_
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="@drawable/channel_leftblock"
android:visibility="gone" />

android:id="@+id/shade_right"
android:layout_
android:layout_
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@drawable/channel_rightblock"
android:visibility="gone" />





android:id="@+id/viewPager"
android:layout_
android:layout_
android:layout_marginLeft="@dimen/dip5"
android:layout_marginRight="@dimen/dip5"
android:layout_marginTop="@dimen/dip10"
android:layout_marginBottom="@dimen/dip10" />


首先是自定义的水平滚动的头部tabview相关类 :

package com.example.webservice.widget.ColumnHorizontalScrollView;

import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;

/**
* 自定义水平滚动的view,带左右阴影效果
* @author xuhaifeng
*
*/
public class ColumnHorizontalScrollView extends HorizontalScrollView {
/** 传入整体布局 */
private View ll_content;
/** 传入拖动栏布局 */
private View rl_column;
/** 左阴影图片 */
private ImageView leftImage;
/** 右阴影图片 */
private ImageView rightImage;
/** 屏幕宽度 */
private int mScreenWitdh = 0;
/** 父类的活动activity */
private Activity activity;

public ColumnHorizontalScrollView(Context context) {
super(context);
}

public ColumnHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);

}

public ColumnHorizontalScrollView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}

/**
* 在拖动的时候执行,主要是为了拖动前后加上阴影效果图
* */
@Override
protected void onScrollChanged(int paramInt1, int paramInt2, int paramInt3,
int paramInt4) {
// TODO Auto-generated method stub
super.onScrollChanged(paramInt1, paramInt2, paramInt3, paramInt4);
shade_ShowOrHide();
if (!activity.isFinishing() && ll_content != null && leftImage != null
&& rightImage != null && rl_column != null) {
if (ll_content.getWidth() <= mScreenWitdh) {
leftImage.setVisibility(View.GONE);
rightImage.setVisibility(View.GONE);
}
} else {
return;
}
if (paramInt1 == 0) {
leftImage.setVisibility(View.GONE);
rightImage.setVisibility(View.VISIBLE);
return;
}
if (ll_content.getWidth() - paramInt1 + rl_column.getLeft() == mScreenWitdh) {
leftImage.setVisibility(View.VISIBLE);
rightImage.setVisibility(View.GONE);
return;
}
leftImage.setVisibility(View.VISIBLE);
rightImage.setVisibility(View.VISIBLE);
}

/**
* 传入父类布局中的资源文件
* */
public void setParam(Activity activity, int mScreenWitdh, View paramView1,
ImageView paramView2, ImageView paramView3, View paramView5) {
this.activity = activity;
this.mScreenWitdh = mScreenWitdh;
ll_cOntent= paramView1;
leftImage = paramView2;
rightImage = paramView3;
rl_column = paramView5;
}

/**
* 判断左右阴影的显示隐藏效果
* */
public void shade_ShowOrHide() {
if (!activity.isFinishing() && ll_content != null) {
measure(0, 0);
// 如果整体宽度小于屏幕宽度的话,那左右阴影都隐藏
if (mScreenWitdh >= getMeasuredWidth()) {
leftImage.setVisibility(View.GONE);
rightImage.setVisibility(View.GONE);
}
} else {
return;
}
// 如果滑动在最左边时候,左边阴影隐藏,右边显示
if (getLeft() == 0) {
leftImage.setVisibility(View.GONE);
rightImage.setVisibility(View.VISIBLE);
return;
}
// 如果滑动在最右边时候,左边阴影显示,右边隐藏
if (getRight() == getMeasuredWidth() - mScreenWitdh) {
leftImage.setVisibility(View.VISIBLE);
rightImage.setVisibility(View.GONE);
return;
}
// 否则,说明在中间位置,左、右阴影都显示
leftImage.setVisibility(View.VISIBLE);
rightImage.setVisibility(View.VISIBLE);
}

}

 

package com.example.webservice.widget.scrollTab;

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

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.example.webservice.R;
import com.example.webservice.bean.TabCode;
/**
*
*

Title:带滑动效果的tab切换控件


*

Description:


* @author xhf
* @date 2014-12-17
*/
public class ScrollTabs extends LinearLayout {

/**
* 滑动图片
*/
private ImageView cursor;
/**
* tab 页外围布局 linerLayout
*/
private LinearLayout tabsLinerLayout;
/**
* 每一屏显示最大的tab页数
*/
private final static int MAX_TABS_NUM = 4;

/**
* 所有tab页的存储
*/
private static List tabsList = null;

/**
* 当前选中的tab
*/
private int currentIndex = 0;

private int layoutWidth;

private OnItemClickListener onItemClickListener;

private boolean isFirstIn = true;
/**
* 父类activity
*/
private Activity mActivity;

/**
* 头部tab标签页数据源
*/
private List lists;

public ScrollTabs(Context context) {
this(context, null);
}

public ScrollTabs(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = LayoutInflater.from(getContext());
LinearLayout tabLinerLayout = (LinearLayout) inflater.inflate(
R.layout.layout_tab, this, true);
tabsLinerLayout = (LinearLayout) tabLinerLayout
.findViewById(R.id.tabLayoutTabs);
cursor = (ImageView) tabLinerLayout.findViewById(R.id.cursor);
}

public ScrollTabs(Context context, AttributeSet attrs, int defStyle) {
this(context, attrs);
}

public void setParams(Activity activity,List tcs)
{
this.mActivity=activity;
this.lists=tcs;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int specModeWidth = MeasureSpec.getMode(widthMeasureSpec);
if( isFirstIn) {
initView();
}
}

private void initView() {
DisplayMetrics dm = new DisplayMetrics();
mActivity.getWindowManager().getDefaultDisplay().getMetrics(dm);
layoutWidth = dm.widthPixels;
Log.i("ScrollTabs", "ScrollTabs getMeasuredWidth" + layoutWidth);
tabsList = new ArrayList();
for (int i = 0; iaddNewTab(lists.get(i));
}
if (cursor != null) {
cursor.setLayoutParams(new FrameLayout.LayoutParams(layoutWidth
/ getTabs(), cursor.getLayoutParams().height));
}
// 设置默认项
if (isFirstIn) {
changeTabCursor(0);
isFirstIn = false;
}
}


/**
* 添加新的tab页
* @param weekIndex
*
*/
public void addNewTab(TabCode tc) {
LinearLayout tabView = getNewTab(tc);
if(tabsLinerLayout!=null) {
tabsLinerLayout.addView(tabView);
}
tabsList.add(tabView);
}



/**
* 生成一个新的tab项
* @param date
* @param weekIndex
* @return
*/
public LinearLayout getNewTab(TabCode tc) {
LayoutInflater inflater = LayoutInflater.from(getContext());
LinearLayout tabLinerLayout = (LinearLayout) inflater.inflate(R.layout.item_tab, null);
if(tabLinerLayout!=null) {
int index = tabsList.size();
tabLinerLayout.setOnClickListener(new TabOnClickListener(index,tc));
TextView txDate = (TextView) tabLinerLayout.findViewById(R.id.tvTabContent);
if(txDate!=null) {
txDate.setText(tc.getName());
}
}
return tabLinerLayout;
}

/**
* 每个tab项点击事件
* @author xhf
*
*/
public class TabOnClickListener implements OnClickListener {

private int index;

private TabCode tc;

public TabOnClickListener(int index,TabCode tc) {
this.index = index;
this.tc=tc;
}

@Override
public void onClick(View v) {
changeTabCursor(index);
if(onItemClickListener!=null) {
onItemClickListener.onItemClick(index,tc);
}
}
}

public interface OnItemClickListener {
public void onItemClick(int index,TabCode tc);
};


/**
* 选中tab表头的变化效果
*
*/
public void changeTabCursor(int targetIndex) {
int currentPostion = getMoveStep(currentIndex);
int targetPostion = getMoveStep(targetIndex);
// 设置选中tab页的字体颜色
for (int i = 0; i LinearLayout tabView = (LinearLayout) tabsList.get(i);
if(tabView!=null) {
TextView txDate = (TextView) tabView.getChildAt(0);
txDate.setWidth(getTabWidth());
if (i == targetIndex) {
txDate.setTextColor(Color.WHITE);
txDate.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources()
.getDimension(R.dimen.sp20));
} else if(i==currentIndex) {
txDate.setTextColor(getResources().getColor(
R.color.defect_text_light_orange));
txDate.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources()
.getDimension(R.dimen.sp17));
}
}
}
Animation animation = new TranslateAnimation(currentPostion,
targetPostion, 0, 0);
animation.setFillAfter(true);
animation.setDuration(300);
if(cursor!=null) {
cursor.startAnimation(animation);
}
currentIndex = targetIndex;
}

/**
* 滑动图片移动位置
*
* @param steps
* @return
*/
private int getMoveStep(int steps) {
int moveStep = 0;
if (steps != 0) {
moveStep = getTabWidth() * steps;
} else {
moveStep = 0;
}
return moveStep;
}

/**
* 每一个tab页宽度
*
* @return
*/
private int getTabWidth() {
return (layoutWidth / getTabs());
}

/**
* 获取tab长度
* @return
*/
private int getTabs() {
return tabsList.size() > MAX_TABS_NUM ? MAX_TABS_NUM : tabsList.size();
}

public void setOnItemClickListener(OnItemClickListener itemClickListener) {
this.OnItemClickListener= itemClickListener;
}
}

涉及到的xml布局:


android:layout_
android:layout_
android:background="@android:color/transparent"
android:orientation="vertical"
android:gravity="center" >

android:id="@+id/tabLayoutTabs"
android:layout_
android:layout_
android:baselineAligned="false"
android:gravity="center"
android:orientation="horizontal"
android:layout_gravity="center">





 

接下来是每个tab item的布局:


android:id="@+id/ll_child"
android:layout_
android:layout_
android:gravity="center"
android:orientation="vertical"
android:layout_gravity="center" >

android:id="@+id/tvTabContent"
android:layout_
android:layout_
android:gravity="center"
android:singleLine="true"
android:textColor="@color/defect_text_light_orange"
android:textSize="12sp"
android:text="12.20" />




实际上在开发过程中每个tab item的信息也是从服务端获取的一个带有id和value的bean实体类,所以在此我也做了实体类封装:

package com.example.webservice.bean;


/**
* 头部滚动tab每个tabItem实体bean类
* @author xhf
*
*/
public class TabCode {

private int code;

private String name;

public int getCode() {
return code;
}

public void setCode(int code) {
this.code = code;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public TabCode()
{
super();
}

public TabCode(int code, String name) {
super();
this.code = code;
this.name = name;
}





}

接下来viewpager需要一个adapter:

/**
*
*/
package com.example.webservice.widget.ColumnHorizontalScrollView;

import java.util.List;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;

/**
* view pager adapter
*
* @author xhf
*
*/
public class ViewPagerAdapter extends FragmentPagerAdapter{

public ViewPagerAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}

private List mFragments;



public List getmFragments() {
return mFragments;
}


public void setmFragments(List mFragments) {
this.mFragments = mFragments;
}


@Override
public int getCount() {
// TODO Auto-generated method stub
return mFragments.size();
}


@Override
public Fragment getItem(int arg0) {
// TODO Auto-generated method stub
return mFragments.get(arg0);
}

}


最后就是自己写的一个用来测试的fragment啦:

package com.example.webservice.widget.ColumnHorizontalScrollView;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import com.example.webservice.R;
/**
* 用来测试viewpager滑动的fragment
* @author xhf
*
*/
public class TabFragment extends Fragment {

private int index=0;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.i("Test","TabFragment");
View view=inflater.inflate(R.layout.fragment_one_button, null);
return view;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
Button btn=(Button)getView().findViewById(R.id.btnTest);
btn.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
((Button)v).setText(String.valueOf(index));
index++;
}
});
}


}



需要修改样式的,就自己修改其中相关的xml布局就好啦~


推荐阅读
author-avatar
林俊雯868043
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有