ViewPager + Fragment 用法总结

      最近看了微信客户端主页面的效果挺不过的,就想模仿搞一个,具体实现步骤如下:

一、新建一个attrs.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- 自定义属性 -->
    <attr name="icon_color_change_tab" format="reference"></attr>
    <attr name="color_change_tab" format="color"></attr>
    <attr name="text_change_tab" format="string"></attr>
    <attr name="text_size_change_tab" format="dimension"></attr>

    <declare-styleable name="ColorChangeTab">
        <attr name="icon_color_change_tab"></attr>
        <attr name="color_change_tab"></attr>
        <attr name="text_change_tab"></attr>
        <attr name="text_size_change_tab"></attr>
    </declare-styleable>
    

</resources>

二、再新建一个java文件,引用上面的自定义控件属性

package com.swun.jkt.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Looper;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import com.swun.jkt.R;


/**
 * 自定义控件需要的步骤如下: 1、自定义属性attr.xml 2、在布局文件中使用自定义属性(命名空间) 3、在自定义控件的构造方法中获取自定义属性
 * 4、onMeasure 5、onDraw
 * 
 * @author littleRich
 * 
 */
public class ColorChangeTab extends View {

	private int mColor = 0xff45c01A;// 图标背景色,绿色
	public static final int TEXT_COLOR = 0xff333333;// 文本默认的颜色(灰色)
	private Bitmap mIconBitmap;// 图标
	private String mText = "";// 图标下的文字
	// 设置默认文字大小为12sp
	private int mTextSize = (int) TypedValue.applyDimension(
			TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics());

	private Canvas mCanvas;// 给图标绘制背景色的画布
	private Bitmap mBitmap;// 图标下的背景色(用于动态修改颜色,出现切换标签的渐变效果)
	private Paint mPaint;
	private float alpha;// 透明度(用户动态修改颜色,出现渐变效果),范围为:0~1

	private Rect mIconRect;
	private Rect mTextBound;// 包裹文字的矩形区域

	private Paint mTextPaint;// 画文字的画笔

	public ColorChangeTab(Context context) {
		// 调用两个参数的构造方法
		this(context, null);
	}

	public ColorChangeTab(Context context, AttributeSet attrs) {
		// 调用三个参数的构造方法
		this(context, attrs, 0);
	}

	public ColorChangeTab(Context context, AttributeSet attrs, int defStyleAttr) {
		// 三个参数的构造方法
		super(context, attrs, defStyleAttr);
		// 获取所有自定义属性的值
		TypedArray mTypedArray = context.obtainStyledAttributes(attrs,
				R.styleable.ColorChangeTab);
		// 获取自定属性的个数
		int count = mTypedArray.getIndexCount();

		/**
		 * 获取所有自定义属性
		 */
		for (int i = 0; i < count; i++) {
			// 获取索引ID
			int ID = mTypedArray.getIndex(i);
			switch (ID) {

			case R.styleable.ColorChangeTab_icon_color_change_tab:// 如果是图标
				BitmapDrawable mBitmapDrawable = (BitmapDrawable) mTypedArray
						.getDrawable(ID);
				mIconBitmap = mBitmapDrawable.getBitmap();
				break;

			case R.styleable.ColorChangeTab_color_change_tab:// 如果是颜色
				mColor = mTypedArray.getColor(ID, 0xff45c01A);
				break;

			case R.styleable.ColorChangeTab_text_change_tab:// 如果是文本内容
				mText = mTypedArray.getString(ID);
				break;

			case R.styleable.ColorChangeTab_text_size_change_tab:// 如果是文本尺寸
				mTextSize = (int) mTypedArray.getDimension(ID, TypedValue
						.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12,
								getResources().getDisplayMetrics()));
				break;

			default:
				break;
			}
		}
		// 回收TypedArray
		mTypedArray.recycle();

		mTextBound = new Rect();// 新建文本矩形区域
		mTextPaint = new Paint();// 新建画笔
		mTextPaint.setTextSize(mTextSize);// 文字大小
		mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);// 测量取得文本区域
																		// 宽度,高度

	}

	/**
	 * 测量大小
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		/**
		 * 获取icon的边长尺寸
		 * 
		 * 说明:icon是正方形,具体取得其边长的算法如下
		 * 
		 * 边长=水平方向剩余空间&垂直方向剩余空间的 最小值
		 * 
		 * 其中,水平方向剩余空间:控件所有长度-左右的padding 垂直方向剩余空间:控件所有高度-上下的padding-文字矩形区域 的高度
		 */
		int iconWidth = Math.min(getMeasuredWidth() - getPaddingLeft()
				- getPaddingRight(), getMeasuredHeight() - getPaddingTop()
				- getPaddingBottom() - mTextBound.height());

		// 左上角的横坐标
		int left = (getMeasuredWidth() - iconWidth) / 2;
		// 左上角的纵坐标
		int right = (getMeasuredHeight() - iconWidth - mTextBound.height()) / 2;
		// icon的矩形区域
		mIconRect = new Rect(left, right, left + iconWidth, right + iconWidth);

	}

	@Override
	protected void onDraw(Canvas canvas) {
		/**
		 * drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint); <br/>
		 * bitmap:具体要绘制的图片 src: 是对图片进行裁截,若是空null则显示整个图片 <br/>
		 * dst:是图片在Canvas画布中显示的区域,<br/>
		 * 大于src则把src的裁截区放大,<br/>
		 * 小于src则把src的裁截区缩小。<br/>
		 * 如果绘制的是bitmap,paint设置为空
		 */
		canvas.drawBitmap(mIconBitmap, null, mIconRect, null);

		// 颜色透明度值;this.alpha为0~1的float值。alpha为0~255的透明度值
		int alpha = (int) Math.ceil(255 * this.alpha);

		// 内存中准备mBitmap:setAlpha,纯色,xfermode,图标
		setupTargetBitmap(alpha);
		// 1、绘制源文本 2、绘制变色的文本
		// 绘制源文本
		drawSourceText(canvas, alpha);
		// 绘制变色的文本
		drawTargetText(canvas, alpha);
		canvas.drawBitmap(mBitmap, 1/2, 1/2, null);
	}

	/**
	 * 设置可变色的文本
	 * @param canvas 画布
	 * @param alpha 绿色的透明度
	 */
	private void drawTargetText(Canvas canvas, int alpha) {
		// 设置绿色,与透明度,以便渐变。
		mTextPaint.setColor(mColor);
		mTextPaint.setAlpha(alpha);
		// 显示文字的左上角的横坐标(在icon下面,并且居中)
		int left = getMeasuredWidth() / 2 - mIconRect.width() / 2;
		// 显示文字的左下角的纵坐标
		int right = mIconRect.bottom + mTextBound.height();
		// 绘制文本
		canvas.drawText(mText, left, right, mTextPaint);
	}

	/**
	 * 绘制源文本。
	 * 
	 * @param canvas
	 *            画布(onDraw()传入)
	 * @param alpha
	 *            透明度
	 */
	private void drawSourceText(Canvas canvas, int alpha) {
		mTextPaint.setAlpha(255 - alpha);//文字透明度
		mTextPaint.setColor(TEXT_COLOR);// 文字颜色(灰色)
		// 显示文字的左上角的横坐标(在icon下面,并且居中)
		int left = getMeasuredWidth() / 2 - mIconRect.width() / 2;
		// 显示文字的左下角的纵坐标
		int right = mIconRect.bottom + mTextBound.height();
		// 绘制文本
		canvas.drawText(mText, left, right, mTextPaint);
	}

	/**
	 * 在内存中绘制可变色的Icon
	 * 
	 * @param alpha
	 *            透明度值(用户动态改变图标,渐变颜色)
	 */
	private void setupTargetBitmap(int alpha) {
		/**
		 * int width -->宽 <br/>
		 * int height -->高 <br/>
		 * Config config --> android.graphics.Bitmap.Config是一个枚举类型,里面定义了位图的四种格式.
		 * ALPHA_8:数字为8,图形参数应该由一个字节来表示,应该是一种8位的位图
		 * ARGB_4444:4+4+4+4=16,图形的参数应该由两个字节来表示,应该是一种16位的位图.
		 * ARGB_8888:8+8+8+8=32,图形的参数应该由四个字节来表示,应该是一种32位的位图.
		 * RGB_565:5+6+5=16,图形的参数应该由两个字节来表示,应该是一种16位的位图.
		 */
		mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
				Config.ARGB_8888);

		// 创建一个纯色的画布
		mCanvas = new Canvas(mBitmap);
		// 创建一支画笔
		mPaint = new Paint();
		mPaint.setColor(mColor);
		// 去锯齿
		mPaint.setAntiAlias(true);
		/**
		 * Dither(图像的抖动处理,当每个颜色值以低于8位表示时,对应图像做抖动处理可以实现在可显示颜色总数比较低(比如256色)
		 * 时还保持较好的显示效果
		 */
		mPaint.setDither(true);
		mPaint.setAlpha(alpha);
		// 在图标范围绘制纯色
		mCanvas.drawRect(mIconRect, mPaint);
		// 设置Xfermode
		mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
		// 将画笔设为不透明
		mPaint.setAlpha(255);
		mCanvas.drawBitmap(mIconBitmap, null, mIconRect, mPaint);
	}
	
	/**
	 * 设置图标的透明度
	 * @param alpha 绿色的透明度值。0~1,为0代表全透明。1代表不透明
	 */
	public void setIconAlpha(float alpha){
		this.alpha = alpha;
		//更新图标
		invalidateView();
	}

	/**
	 * 重绘我们的控件
	 * 注意。我们需要判断是否是主线程。如果是主线程,直接调用invalidate()
	 * 非主线程,调用postInvalidate();
	 */
	private void invalidateView() {
		//如果这是主线程提出更新
		if(Looper.getMainLooper() == Looper.myLooper()){
			invalidate();
		}
		//如果不是主线程
		else{
			postInvalidate();
		}
	}

	//当控件暂时被系统回收后,保存数据
	@Override
	protected Parcelable onSaveInstanceState() {
		Bundle bundle = new Bundle();
		bundle.putFloat("alpha", alpha);
		bundle.putParcelable("parentData", super.onSaveInstanceState());
		return bundle;
	}

	//当控件恢复时,恢复暂存数据
	@Override
	protected void onRestoreInstanceState(Parcelable state) {
		if(state instanceof Bundle){
			alpha = ((Bundle) state).getFloat("alpha");
			super.onRestoreInstanceState(((Bundle) state).getParcelable("parentData"));
		}
		return ;
	}
	
	
	

}



三、自定义底部Tab完成,下面可以使用了,创建一个java文件,继承自FragmentActivity



0、写一个fragment文件

/**
 * 
 */package com.swun.jkt.fragment;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/** 
 * @author: littleRich
 * @date: 2015-8-9 上午11:20:27 
 * @version 1.0 
 * @parameter  
 * @since  
 * @return  
 */

public class IMFragment extends Fragment {
	/* (non-Javadoc)
	 * @see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
	 */
	@Override
	public View onCreateView(LayoutInflater inflater,
			@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
		TextView tv = new TextView(getActivity());
		tv.setText("world");
		
		return tv;
	}
}


1、接着使用上面的fragment文件,布局代码如下:

<LinearLayout 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"
    android:orientation="vertical"
    tools:context="com.swun.jkt.ChangeTab" >
    
   <!-- 上部actionbar部分 -->
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="50dp"
        android:background="#cc2c72d0" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:textSize="20sp"
             android:background="#00000000"
             android:textColor="#FFFFFFFF"
            android:text="消息中心" />

        <ImageButton
            android:id="@+id/id_back"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_alignParentLeft="true"
            android:layout_marginTop="4dp"
            android:layout_marginLeft="10dp"
            android:background="#00000000"
            android:src="@drawable/back_1" />
        <ImageView
            android:id="@+id/id_sms"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="15dp"
            android:src="@drawable/ic_menu_end_conversation" />

    </RelativeLayout>
    
    
    
    
    
    
    
	<!-- ViewPager部分 -->
    <android.support.v4.view.ViewPager
        android:id="@+id/id_vp_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</pre><pre name="code" class="java">
</pre><pre name="code" class="java"><span style="white-space:pre">	</span><pre name="code" class="java"><!-- 底部自定义Tab选项部分 -->

 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <com.swun.jkt.view.ColorChangeTab
            xmlns:colortab="http://schemas.android.com/apk/res/com.swun.jkt"
            android:id="@+id/aty_msgcenter_msg"
            android:layout_width="0dp"
            android:layout_height="60dp"
            android:layout_weight="1"
            android:padding="5dp"
             colortab:text_change_tab = "聊天" 
            colortab:icon_color_change_tab="@drawable/ic_launcher"
            colortab:color_change_tab="#ff45c01a" />

        <com.swun.jkt.view.ColorChangeTab
            xmlns:colortab="http://schemas.android.com/apk/res/com.swun.jkt"
            android:id="@+id/aty_msgcenter_message"
            android:layout_width="0dp"
            android:layout_height="60dp"
            android:layout_weight="1"
            android:padding="5dp"
            colortab:icon_color_change_tab="@drawable/ic_msg_new"
            colortab:color_change_tab="#ff45c01a"
            colortab:text_change_tab = "消息" />
    </LinearLayout>

</LinearLayout>
</pre><pre name="code" class="java"><span style="white-space:pre">	</span>2、java代码如下:
<span style="white-space:pre">	</span><pre name="code" class="java">package com.swun.jkt;

import java.util.ArrayList;

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.view.View;

import com.swun.jkt.Adapter.MsgFragmentAdapter;
import com.swun.jkt.fragment.IMFragment;
import com.swun.jkt.fragment.MsgFragment;
import com.swun.jkt.fragment.MsgFragment_;
import com.swun.jkt.view.ColorChangeTab;

public class ChangeTab extends FragmentActivity {

	private ColorChangeTab tab1;
	private ColorChangeTab tab2;
	/**
	 * ViewPager容器对象,用于填充Fragment对象
	 */
	private ViewPager content_vp;
	/**
	 * 将多个Fragment分页对象放进集合中
	 */
	private ArrayList<Fragment> fragment_ls;
	/**
	 * 用于存放底部几个Tab选项
	 */
	private ArrayList<ColorChangeTab> tab_ls;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_change_tab);
		findView();
		
		fragment_ls = new ArrayList<Fragment>();
		tab_ls = new ArrayList<ColorChangeTab>();
		tab_ls.add(tab1);
		tab_ls.add(tab2);
		MsgFragment mMsgFragment = new MsgFragment_();
		fragment_ls.add(mMsgFragment);
		IMFragment mImFragment = new IMFragment();
		fragment_ls.add(mImFragment);
		
		MsgFragmentAdapter mMsgFragmentAdapter = new MsgFragmentAdapter(getSupportFragmentManager(), fragment_ls);
		content_vp.setAdapter(mMsgFragmentAdapter);
		
		// 自定义控件的点击事件监听器
		onColorTabsClickListener colorTabsClickListener = new onColorTabsClickListener();
		// 为所有自定义控件设置监听器
		for (ColorChangeTab tab : tab_ls) {
			tab.setOnClickListener(colorTabsClickListener);
		}
		tab_ls.get(0).setIconAlpha(1);
		
		// ViewPager的监听器
		viewPagerListener viewPagerLis = new viewPagerListener();
		// 给ViewPager设置监听器
		content_vp.setOnPageChangeListener(viewPagerLis);
		
	}

	/**
	 * 
	 */
	private void findView() {
		tab1 = (ColorChangeTab)findViewById(R.id.aty_msgcenter_msg);
		tab2 = (ColorChangeTab)findViewById(R.id.aty_msgcenter_message);
		content_vp = (ViewPager)findViewById(R.id.id_vp_content);
		
	}
	
	private class onColorTabsClickListener implements View.OnClickListener {

		@Override
		public void onClick(View v) {
			resetTabColor();
			int ID = v.getId();
			switch (ID) {
			case R.id.aty_msgcenter_msg:
				content_vp.setCurrentItem(0, false);
				tab_ls.get(0).setIconAlpha(1);
				break;
			case R.id.aty_msgcenter_message:
				content_vp.setCurrentItem(1, false);
				tab_ls.get(1).setIconAlpha(1);
				break;
			}
		}

	}
	/**
	 * 重置自定义控件的透明度
	 */
	private void resetTabColor() {
		for (ColorChangeTab tab : tab_ls) {
			tab.setIconAlpha(0);
		}
	}

	private class viewPagerListener implements OnPageChangeListener {

		@Override
		public void onPageScrollStateChanged(int arg0) {
		}

		@Override
		public void onPageScrolled(int position, float offset, int offsetPixels) {
			updateTabColor(position, offset);
		}

		@Override
		public void onPageSelected(int arg0) {
		}

	}

	/**
	 * 当页面滑动的时候,动态更新底部Tab标签的颜色(该变暗的变暗,改变明显的变明显)
	 * 
	 * @param position
	 *            当前第几个Fragment
	 * @param offset
	 *            当前滑动的偏移值(从0~1或者从1~0)
	 */
	private void updateTabColor(int position, float offset) {
		if (offset > 0) {
			tab_ls.get(position).setIconAlpha(1 - offset);
			tab_ls.get(position + 1).setIconAlpha(offset);
		}
	}

}
</pre><pre name="code" class="java">
</pre><pre>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ViewPagerFragment 是 Android 开发中常用的组件,ViewPager 可以实现左右滑动切换不同的页面,而 Fragment 可以实现模块化开发,将界面和逻辑分离,便于维护和扩展。 将两者结合起来可以实现多个 FragmentViewPager 中的左右滑动切换。具体实现步骤如下: 1. 创建多个 Fragment,每个 Fragment 对应一个页面。 2. 创建一个继承自 FragmentPagerAdapter 或 FragmentStatePagerAdapter 的适配器类,重写 getItem() 方法,返回对应位置的 Fragment。 3. 在布局文件中添加 ViewPager 组件,并设置适配器。 4. (可选)设置 ViewPager 的页面切换动画效果。 示例代码: 1. 创建 Fragment: ``` public class MyFragment extends Fragment { // ... } ``` 2. 创建适配器: ``` public class MyPagerAdapter extends FragmentPagerAdapter { private List<Fragment> fragmentList; public MyPagerAdapter(FragmentManager fm, List<Fragment> fragmentList) { super(fm); this.fragmentList = fragmentList; } @Override public Fragment getItem(int position) { return fragmentList.get(position); } @Override public int getCount() { return fragmentList.size(); } } ``` 3. 在布局文件中添加 ViewPager 组件: ``` <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 4. 设置适配器: ``` List<Fragment> fragmentList = new ArrayList<>(); fragmentList.add(new MyFragment()); fragmentList.add(new MyFragment()); fragmentList.add(new MyFragment()); ViewPager viewPager = findViewById(R.id.view_pager); viewPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager(), fragmentList)); ``` 5. (可选)设置页面切换动画效果: ``` viewPager.setPageTransformer(true, new DepthPageTransformer()); ``` 以上是 ViewPagerFragment 的基本用法,你还可以根据实际需求对它们进行更多的扩展和定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值