首先我们先来看一下我们实现的效果
这个就是我们的效果 别看我们的效果简单 我们主要实现的功能有 viewpager和上面的tab标题可以联动 自定义的三角形角标指示器 文字选中高亮 动态加载布局 和fragment
下面就让我们一起看一下这个神奇的效果是怎么实现的吧
首先我们需要的是布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
***xmlns:hyman="http://schemas.android.com/apk/res/com.example.viewpager"***
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:orientation="vertical" >
<com.example.view.ViewPagerIndicator
android:id="@+id/id_incicator"
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="#000"
android:orientation="horizontal"
***hyman:visible_tab_count="4"***
>
</com.example.view.ViewPagerIndicator>
<android.support.v4.view.ViewPager
android:id="@+id/id_viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</android.support.v4.view.ViewPager>
</LinearLayout>
在布局文件中 我们使用到自定义的属性和自定义的布局
首先我们先看一下自定义属性中的实现代码 我们现在values下面创建一个名称为attr.xml的文件 文件中的代码是
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr
name="visible_tab_count" format="integer"
/>
<declare-styleable
name="ViewPagerIndicator"
>
<attr
name="visible_tab_count"
/>
</declare-styleable>
</resources>
这样我们的自定义属性就能在布局文件中使用了 首先需要标明自定义的空间 然后我们一起去看一看自定义的布局文件
import java.util.List;
import com.example.viewpager.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Paint.Style;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ViewPagerIndicator extends LinearLayout {
private Paint mPaint;
private Path mPath;
private int mTriangleWidth;
private int mTriangleHeight;
private static final float RADIO_TRIANGLE_WIDTH = 1 / 6F;
/**
* 三角形的底边的最大宽度
*/
private final int DIMENSION_TRIANGLE_WIDTH_MAX=(int) (getScreenWidth()/3*RADIO_TRIANGLE_WIDTH);
private int mInitTranslationX;
private int mTranslationX;
private int mTabVisibleCount;
private static final int COUNT_DEFAULT_TAB = 4;
private List<String> mTitles;
private static final int COLOR_TEXT_NORMAL = 0x77FFFFFF;
private static final int COLOR_TEXT_HIGHLIGHT = 0xFFFFFFFF;
private ViewPager mViewPager;
private PageOnchangeListener mListener;
public ViewPagerIndicator(Context context, AttributeSet attrs, int defStyle) {
this(context, attrs);
}
public ViewPagerIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
// 获取可见的tab的数量
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.ViewPagerIndicator);
mTabVisibleCount = a.getInt(
R.styleable.ViewPagerIndicator_visible_tab_count,
COUNT_DEFAULT_TAB);
if (mTabVisibleCount < 0) {
mTabVisibleCount = COUNT_DEFAULT_TAB;
}
a.recycle();
// 初始化画笔
mPaint = new Paint();
mPaint.setAntiAlias(true);// 设置钢锯齿
// 设置画笔的颜色
mPaint.setColor(Color.parseColor("#ffffffff"));
mPaint.setStyle(Style.FILL);
mPaint.setPathEffect(new CornerPathEffect(3));// 三角形顶尖的锐度 不要太尖
}
public ViewPagerIndicator(Context context) {
this(context, null);// 默认调用两个参数的构造方法
}
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.save();
canvas.translate(mInitTranslationX + mTranslationX, getHeight() + 2);// 高度降低一点
canvas.drawPath(mPath, mPaint);
canvas.restore();
super.dispatchDraw(canvas);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mTriangleWidth = (int) (w / mTabVisibleCount * RADIO_TRIANGLE_WIDTH);// 绘制的三角形底边的宽度
mTriangleWidth=Math.min(mTriangleWidth, DIMENSION_TRIANGLE_WIDTH_MAX);//在最大值和最小值中选择一个最小的
mInitTranslationX = (w / mTabVisibleCount - mTriangleWidth) / 2;// tab的一个偏移量
// 就是设置三角形在米一个tab的正中间
initTriangle();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
int cCount = getChildCount();
if (cCount == 0)
return;
for (int i = 0; i < cCount; i++) {
// 获得每一个子view
View view = getChildAt(i);
LinearLayout.LayoutParams lp = (LayoutParams) view
.getLayoutParams();
lp.weight = 0;
lp.width = getScreenWidth() / mTabVisibleCount;
view.setLayoutParams(lp);
}
setItemClickEvent();
}
/**
* 获得屏幕的宽度
*
* @return
*/
public int getScreenWidth() {
WindowManager wm = (WindowManager) getContext().getSystemService(
Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
return metrics.widthPixels;// 返回屏幕的宽度
}
/**
* 初始化三角形
*/
private void initTriangle() {
// 设置三角形的宽度
mTriangleHeight = mTriangleWidth / 2;
// 初始化path;
mPath = new Path();
// 将线移动的(0,0)的位置 开始划线
mPath.moveTo(0, 0);
mPath.lineTo(mTriangleWidth, 0);
// 在Android中 纵坐标向下为正 所以高度设置为负值
mPath.lineTo(mTriangleWidth / 2, -mTriangleHeight);
mPath.close();
}
public void scroll(int position, float Offset) {
int tabWidth = getWidth() / mTabVisibleCount;
mTranslationX = (int) (tabWidth * (position + Offset));
if (position >= (mTabVisibleCount - 2) && Offset > 0
&& getChildCount() > mTabVisibleCount) {
if (mTabVisibleCount != 1) {
this.scrollTo((position - (mTabVisibleCount - 2)) * tabWidth
+ (int) Offset * tabWidth, 0);
} else {
this.scrollTo(position * tabWidth + (int) Offset * tabWidth, 0);
}
}
invalidate();
}
public void setTabItemTitles(List<String> titles) {
if (titles != null && titles.size() > 0) {
this.removeAllViews();
mTitles = titles;
for (String title : mTitles) {
addView(generateTextView(title));
}
setItemClickEvent();
}
}
/**
* 设置可见的tab数量
*
* @param count
*/
public void setVisibleTabCount(int count) {
mTabVisibleCount = count;
}
/**
* 根据title创建tab
*
* @param title
* @return
*/
private View generateTextView(String title) {
TextView tv = new TextView(getContext());
LinearLayout.LayoutParams lp = new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lp.width = getScreenWidth() / mTabVisibleCount;
tv.setText(title);
tv.setGravity(Gravity.CENTER);
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
tv.setTextColor(COLOR_TEXT_NORMAL);
tv.setLayoutParams(lp);
return tv;
}
public interface PageOnchangeListener{
public void onPageSelected(int position);
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels);
public void onPageScrollStateChanged(int state);
}
public void setOnPageChangeListener(PageOnchangeListener listener) {
this.mListener=listener;
}
/**
* 设置关联的ViewPager
*
* @param viewPager
* @param pos
*/
public void setViewPager(ViewPager viewPager, int pos) {
mViewPager = viewPager;
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
if (mListener!=null) {
mListener.onPageSelected(arg0);
}
highLightTextView(arg0);
}
@Override
public void onPageScrolled(int position, float positionOffset,
int arg2) {
// tabwidth*positionoffset+tabwidth*position;
scroll(position, positionOffset);
if (mListener!=null) {
mListener.onPageScrolled(position, positionOffset, arg2);
}
}
@Override
public void onPageScrollStateChanged(int arg0) {
if (mListener!=null) {
mListener.onPageScrollStateChanged(arg0);
}
}
});
mViewPager.setCurrentItem(pos);
highLightTextView(pos);
}
/**
* 重置TAB文本的颜色
* @param pos
*/
public void resetTextViewColor(){
for (int i = 0; i <getChildCount(); i++) {
View view=getChildAt(i);
if (view instanceof TextView) {
((TextView) view).setTextColor(COLOR_TEXT_NORMAL);
}
}
}
/*
* 高亮某个tab的文本
*/
public void highLightTextView(int pos){
resetTextViewColor();
View view=getChildAt(pos);
if (view instanceof TextView) {
((TextView) view).setTextColor(COLOR_TEXT_HIGHLIGHT);
}
}
/**
* 设置Tab的点击事件
*/
public void setItemClickEvent() {
int cCount=getChildCount();
for (int i = 0; i < cCount; i++) {
final int j=i;
View view=getChildAt(i);
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mViewPager.setCurrentItem(j);
}
});
}
}
}
然后我们下面的代码是实现fragment动态的一个加载 让我们一起看一看fragment中的实现代码
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class VpSimpleFragment extends Fragment {
private String mTitle;
public static final String BUNDLE_TITLE="title";
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Bundle bundle=getArguments();
if (bundle!=null) {
mTitle=bundle.getString(BUNDLE_TITLE);
}
TextView tv=new TextView(getActivity());
tv.setText(mTitle);
tv.setGravity(Gravity.CENTER);
return tv;
}
public static VpSimpleFragment newInstance(String title){
Bundle bundle=new Bundle();
bundle.putString(BUNDLE_TITLE, title);
VpSimpleFragment fragment=new VpSimpleFragment();
fragment.setArguments(bundle);
return fragment;
}
}
最后所有的代码准备好 还是在主类中实现调用 话不多说 看一看主类中的实现代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.example.view.ViewPagerIndicator;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.view.Window;
public class MainActivity extends FragmentActivity {
private ViewPager mViewPager;
private ViewPagerIndicator mIndicator;
private List<String> mTitles=Arrays.asList("短信1","收藏2","推荐3","短信4","收藏5","推荐6","短信7","收藏8","推荐9");
private List<VpSimpleFragment> mContents=new ArrayList<VpSimpleFragment>();
private FragmentPagerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//隐藏actionbar
requestWindowFeature(Window.FEATURE_NO_TITLE);
//加载布局文件
setContentView(R.layout.activity_main2);
initViews();
initDatas();
mIndicator.setVisibleTabCount(3);
mIndicator.setTabItemTitles(mTitles);
mViewPager.setAdapter(adapter);
mIndicator.setViewPager(mViewPager, 0);
}
private void initDatas() {
for(String title:mTitles){
VpSimpleFragment fragment = VpSimpleFragment.newInstance(title);
mContents.add(fragment);
}
adapter=new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public int getCount() {
return mContents.size();
}
@Override
public Fragment getItem(int arg0) {
return mContents.get(arg0);
}
};
}
private void initViews() {
//控件初始化
mViewPager=(ViewPager) findViewById(R.id.id_viewpager);
mIndicator=(ViewPagerIndicator) findViewById(R.id.id_incicator);
}
}
上面这些代码 就实现了我们需要的一般的框架 快快行动吧 学习 会自定义是获得高新的必要 创新的起步