初学Android项目:开发电子市场<第一天>

以前,都是自己看别人写的博客。总在各位大神之间流离,寻找属于自己的那一块代码块。今天,也不知道怎么了,忽然自己也想养成这种习惯。我想,我也应该从今天开始养成这种习惯了。

嘿嘿,偶尔抒发下自己的小心情。开始工作哟...

各界大神,这只是小弟,自学Android视频,学习归纳的。方便自己以后复习。嘿嘿,温故而知新吧!!!


今天的学习心得:

嘿嘿,先看一下效果图(带有分析)


一.开发类似的电子市场,主要是向用户展示一些常用的应用的下载。

二.搭建框架:

2.1:写全局的基类:BaseApplication.java

2.2:写所有Activity的基类:BaseActivity.java

2.3:导入常用的工具类(老师给的,保存下来,以后会常用,嘿嘿...)

*2.4:自定义控件:PagerTab.java

2.5:写创建Fragment的工厂类:FragmentFactory.java

代码展示:

全局的基类:BaseApplication.java


package com.example.application;
import android.app.Application;
import android.os.Handler;
import android.os.Looper;
public class BaseApplication extends Application {
	//获取全局的上下文
	private static Application mContext;
	//获取主线程的Handler
	private static Handler mMainThreadHandler;
	//获取主线程的Looper
	private static Looper mMainThreadLooper;
	//获取主线程
	private static Thread mMainThread;
	//获取主线程的id
	private static int mMainThreadId;
	@Override
	public void onCreate() {
		super.onCreate();
		mContext = this;
		mMainThreadHandler = new Handler();
		mMainThreadLooper = getMainLooper();
		mMainThread = Thread.currentThread();
		mMainThreadId = android.os.Process.myTid();
	}
	
	public static Application getApplication() {
		return mContext;
	}
	public static Handler getMainThreadHandler() {
		return mMainThreadHandler;
	}
	public static Looper getMainThreadLooper() {
		return mMainThreadLooper;
	}
	public static Thread getMainThread() {
		return mMainThread;
	}
	public static int getMainThreadId() {
		return mMainThreadId;
	}
}

写所有Activity的基类:BaseActivity.java

package com.example;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
public abstract class BaseActivity extends ActionBarActivity {
	public static BaseActivity getForegroundActivity = null;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		/**初始化数据*/
		init();
		/**初始化view*/
		initView();
		/**初始化actionBar*/
		initActionBar();
	}
	/**Activity界面获得焦点的时候,调用该方法*/
	@Override
	protected void onResume() {
		getForegroundActivity = this;
		super.onResume();
	}
	//获取到前台的activity
	public static BaseActivity getForegroundActivity(){
		return getForegroundActivity();
	}

	public abstract void initActionBar();

	public abstract void initView();

	public abstract void init();
}


MainActivity.java

package com.example;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.support.v7.app.ActionBar;

import com.btt.ui.widget.PagerTab;
import com.example.fragment.FragmentFactory;
import com.example.utils.UIUtils;

public class MainActivity extends BaseActivity implements OnPageChangeListener {
	private ActionBar actionBar;

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

	@Override
	public void initActionBar() {
		actionBar = getSupportActionBar();
	}

	@Override
	public void initView() {
		setContentView(R.layout.activity_main);
		// 1.获取页面title一栏(自定义的)
		PagerTab tabs = (PagerTab) findViewById(R.id.tabs);
		// 2.获取页面ViewPager
		ViewPager pager = (ViewPager) findViewById(R.id.pager);
		// 3.定义ViewPagerAdapter
		ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
		// 将adapter设置到ViewPager中
		pager.setAdapter(adapter);
		// 4.让ViewPager和title绑定到一起
		tabs.setViewPager(pager);
		// 5.设置title的监听事件,监听页面的改变
		tabs.setOnPageChangeListener(this);

	}

	private class ViewPagerAdapter extends FragmentStatePagerAdapter {

		private String[] tab_names;

		public ViewPagerAdapter(FragmentManager fm) {
			super(fm);
			tab_names = UIUtils.getStringArray(R.array.tab_names);
		}

		// 设置ViewPager的title
		@Override
		public CharSequence getPageTitle(int position) {
			return tab_names[position];
		}

		@Override
		public Fragment getItem(int position) {
			return FragmentFactory.createFragment(position);
		}
		//设置ViewPager标题的总数
		@Override
		public int getCount() {
			return tab_names.length;
		}

	}

	@Override
	public void init() {

	}

	@Override
	public void onPageScrollStateChanged(int arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onPageScrolled(int arg0, float arg1, int arg2) {
		// TODO Auto-generated method stub

	}
	/**
	 *选择页面
	 */
	@Override
	public void onPageSelected(int position) {
		
	}

}

自定义控件:PagerTab.java

按照老师的思路写的,嘻嘻...

package com.btt.ui.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.support.v4.widget.EdgeEffectCompat;
import android.support.v4.widget.ScrollerCompat;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.widget.ImageButton;
import android.widget.TextView;

import com.example.BaseActivity;
import com.example.R;
import com.example.utils.UIUtils;

public class PagerTab extends ViewGroup {

	private ViewPager mViewPager;
	private PageListener mPageListener = new PageListener();//用于注册给ViewPager监听状态和滚动
	private OnPageChangeListener mDelegatePageListener;//用于通知外界ViewPager的状态和滚动
	private BaseActivity mActivity;

	private int mDividerPadding = 12;// 分割线上下的padding
	private int mDividerWidth = 1;// 分割线的宽度
	private int mDividerColor = 0x1A000000;//分割线颜色
	private Paint mDividerPaint;//分割线的画笔

	private int mIndicatorHeight = 4;//指示器的高度
	private int mIndicatorWidth;//指示器的宽度,是动态的随着tab的宽度变化
	private int mIndicatorLeft;//指示器的距离左边的距离
	private int mIndicatorColor = 0xFF0084FF;//指示器颜色
	private Paint mIndicatorPaint; //指示器的画笔

	private int mContentWidth;//记录自身内容的宽度
	private int mContentHeight;//记录自身内容的高度

	private int mTabPadding = 24;// tab左右的内边距
	private int mTabTextSize = 16; //tab文字大小
	private int mTabBackgroundResId = R.drawable.bg_tab_text;// tab背景资源
	private int mTabTextColorResId = R.color.tab_text_color; //tab文字颜色
	private int mTabCount;//tab的个数

	private int mCurrentPosition = 0;//当前光标所处的tab,规则是以光标的最左端所在的item的position
	private float mCurrentOffsetPixels;//光标左边距离当前光标所处的tab的左边距离
	private int mSelectedPosition = 0; //当前被选中的tab,用于记录手指点击tab的position

	private boolean mIsBeingDragged = false;//是否处于拖动中
	private float mLastMotionX;//上一次手指触摸的x坐标
	private VelocityTracker mVelocityTracker;//用于记录速度的帮助类
	private int mMinimumVelocity;//系统默认的最小满足fling的速度
	private int mMaximumVelocity;//系统默认最大的fling速度
	private int mTouchSlop;//系统默认满足滑动的最小位移

	private ScrollerCompat mScroller;//处理滚动的帮助者
	private int mLastScrollX;//记录上一次滚动的x位置,这是用于处理overScroll,实际位置可能会受到限制

	private int mMaxScrollX = 0;// 控件最大可滚动的距离
	private int mSplitScrollX = 0;// 根据item的个数,计算出每移动一个item控件需要移动的距离

	private EdgeEffectCompat mLeftEdge;//处理overScroll的反馈效果
	private EdgeEffectCompat mRightEdge;

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

	public PagerTab(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public PagerTab(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		if (context instanceof BaseActivity) {
			mActivity = (BaseActivity) context;
		}
		init();
		initPaint();
	}

	/** 初始化一些常量 */
	private void init() {
		//把一个值从dip转换成px
		mIndicatorHeight = UIUtils.dip2px(mIndicatorHeight);
		mDividerPadding = UIUtils.dip2px(mDividerPadding);
		mTabPadding = UIUtils.dip2px(mTabPadding);
		mDividerWidth = UIUtils.dip2px(mDividerWidth);
		mTabTextSize = UIUtils.dip2px(mTabTextSize);
		//创建一个scroller
		mScroller = ScrollerCompat.create(mActivity);
		//获取一个系统关于View的常量配置类
		final ViewConfiguration configuration = ViewConfiguration.get(mActivity);
		//获取滑动的最小距离
		mTouchSlop = configuration.getScaledTouchSlop();
		//获取fling的最小速度
		mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
		//获取fling的最大速度
		mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();

		mLeftEdge = new EdgeEffectCompat(mActivity);
		mRightEdge = new EdgeEffectCompat(mActivity);
	}

	/** 初始化笔 */
	private void initPaint() {
		mIndicatorPaint = new Paint();
		mIndicatorPaint.setAntiAlias(true);
		mIndicatorPaint.setStyle(Paint.Style.FILL);
		mIndicatorPaint.setColor(mIndicatorColor);

		mDividerPaint = new Paint();
		mDividerPaint.setAntiAlias(true);
		mDividerPaint.setStrokeWidth(mDividerWidth);
		mDividerPaint.setColor(mDividerColor);
	}

	/** 设置ViewPager */
	public void setViewPager(ViewPager viewPager) {
		if (viewPager == null || viewPager.getAdapter() == null) {
			throw new IllegalStateException("ViewPager is null or ViewPager does not have adapter instance.");
		}
		mViewPager = viewPager;
		onViewPagerChanged();
	}

	private void onViewPagerChanged() {
		mViewPager.setOnPageChangeListener(mPageListener);//给ViewPager设置监听
		mTabCount = mViewPager.getAdapter().getCount();//有多少个tab需要看ViewPager有多少个页面
		for (int i = 0; i < mTabCount; i++) {
			if (mViewPager.getAdapter() instanceof IconTabProvider) {//如果想要使用icon作为tab,则需要adapter实现IconTabProvider接口
				addIconTab(i, ((IconTabProvider) mViewPager.getAdapter()).getPageIconResId(i));
			} else {
				addTextTab(i, mViewPager.getAdapter().getPageTitle(i).toString());
			}
		}
		ViewTreeObserver viewTreeObserver = getViewTreeObserver();
		if (viewTreeObserver != null) {//监听第一个的全局layout事件,来设置当前的mCurrentPosition,显示对应的tab
			viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
				@Override
				public void onGlobalLayout() {
					getViewTreeObserver().removeGlobalOnLayoutListener(this);//只需要监听一次,之后通过listener回调即可
					mCurrentPosition = mViewPager.getCurrentItem();
					if (mDelegatePageListener != null) {
						mDelegatePageListener.onPageSelected(mCurrentPosition);
					}
				}
			});
		}
	}

	/** 设置监听,因为Tab会监听ViewPager的状态,所以不要给ViewPager设置监听了,设置给Tab,由Tab转发 */
	public void setOnPageChangeListener(OnPageChangeListener listener) {
		mDelegatePageListener = listener;
	}

	/** 添加文字tab */
	private void addTextTab(final int position, String title) {
		TextView tab = new TextView(mActivity);
		tab.setText(title);
		tab.setGravity(Gravity.CENTER);
		tab.setSingleLine();
		tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTabTextSize);
		tab.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
		tab.setTextColor(UIUtils.getColorStateList(mTabTextColorResId));
		tab.setBackgroundDrawable(UIUtils.getDrawable(mTabBackgroundResId));
		tab.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
		addTab(position, tab);
	}

	/** 添加图片icon */
	private void addIconTab(final int position, int resId) {
		ImageButton tab = new ImageButton(mActivity);
		tab.setImageResource(resId);
		tab.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
		addTab(position, tab);
	}

	private void addTab(final int position, View tab) {
		tab.setFocusable(true);
		//设置tab的点击事件,当tab被点击时候切换pager的页面
		tab.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				mViewPager.setCurrentItem(position);
			}
		});
		tab.setPadding(mTabPadding, 0, mTabPadding, 0);
		addView(tab, position);
	}

	/** 测量时的回调 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// 获取控件自身的宽高,模式
		int widthSize = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
		int heightSize = MeasureSpec.getSize(heightMeasureSpec) - getPaddingBottom() - getPaddingBottom();
		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		int heightMode = MeasureSpec.getMode(heightMeasureSpec);

		int totalWidth = 0;
		int highest = 0;
		int goneChildCount = 0;
		for (int i = 0; i < mTabCount; i++) {
			final View child = getChildAt(i);
			if (child == null || child.getVisibility() == View.GONE) {
				goneChildCount--;
				continue;
			}
			int childWidthMeasureSpec;
			int childHeightMeasureSpec;

			LayoutParams childLayoutParams = child.getLayoutParams();
			if (childLayoutParams == null) {
				childLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
			}

			if (childLayoutParams.width == LayoutParams.MATCH_PARENT) {
				childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
			} else if (childLayoutParams.width == LayoutParams.WRAP_CONTENT) {
				childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST);
			} else {
				childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childLayoutParams.width, MeasureSpec.EXACTLY);
			}

			if (childLayoutParams.height == LayoutParams.MATCH_PARENT) {
				childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
			} else if (childLayoutParams.height == LayoutParams.WRAP_CONTENT) {
				childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST);
			} else {
				childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childLayoutParams.height, MeasureSpec.EXACTLY);
			}

			child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

			int childWidth = child.getMeasuredWidth();
			int childHeight = child.getMeasuredHeight();

			totalWidth += childWidth;
			highest = highest < childHeight ? childHeight : highest;
		}

		if (totalWidth <= widthSize) {//如果子Tab的总宽度小于PagerTab,则采用平分模式
			int splitWidth = (int) (widthSize / (mTabCount - goneChildCount + 0.0f) + 0.5f);
			for (int i = 0; i < mTabCount; i++) {
				final View child = getChildAt(i);
				if (child == null || child.getVisibility() == View.GONE) {
					continue;
				}
				int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(splitWidth, MeasureSpec.EXACTLY);
				int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY);
				child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
			}
			mMaxScrollX = 0;
			mSplitScrollX = 0;
		} else {//如果所有子View大于控件的宽度
			mMaxScrollX = totalWidth - widthSize;
			mSplitScrollX = (int) (mMaxScrollX / (mTabCount - goneChildCount - 1.0f) + 0.5f);
		}

		if (widthMode == MeasureSpec.EXACTLY) {
			mContentWidth = widthSize;
		} else {
			mContentWidth = totalWidth;
		}

		if (heightMode == MeasureSpec.EXACTLY) {
			mContentHeight = heightSize;
		} else {
			mContentHeight = highest;
		}

		int measureWidth = mContentWidth + getPaddingLeft() + getPaddingRight();
		int measureHeight = mContentHeight + getPaddingTop() + getPaddingBottom();
		setMeasuredDimension(measureWidth, measureHeight);
	}

	/** 布局时的回调 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {//这里简化了,没有考虑margin的情况
		if (changed) {
			int height = b - t;//控件供子View显示的高度
			int left = l;
			for (int i = 0; i < mTabCount; i++) {
				final View child = getChildAt(i);
				if (child == null || child.getVisibility() == View.GONE) {
					continue;
				}
				int top = (int) ((height - child.getMeasuredHeight()) / 2.0f + 0.5f);//如果控件比tab要高,则居中显示
				int right = left + child.getMeasuredWidth();
				child.layout(left, top, right, top + child.getMeasuredHeight());//摆放tab
				left = right;//因为是水平摆放的,所以为下一个准备left值
			}
		}
	}

	/** 绘制时的回调 */
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		final int height = getHeight();
		//画指示器
		canvas.drawRect(mIndicatorLeft, height - mIndicatorHeight, mIndicatorLeft + mIndicatorWidth, height, mIndicatorPaint);

		// 画分割线
		for (int i = 0; i < mTabCount - 1; i++) {//分割线的个数比tab的个数少一个
			final View child = getChildAt(i);
			if (child == null || child.getVisibility() == View.GONE) {
				continue;
			}
			if (child != null) {
				canvas.drawLine(child.getRight(), mDividerPadding, child.getRight(), mContentHeight - mDividerPadding, mDividerPaint);
			}
		}
		// 因为overScroll效果是一个持续效果,所以需要持续画
		boolean needsInvalidate = false;
		if (!mLeftEdge.isFinished()) {//如果效果没停止
			final int restoreCount = canvas.save();//先保存当前画布
			final int heightEdge = getHeight() - getPaddingTop() - getPaddingBottom();
			final int widthEdge = getWidth();
			canvas.rotate(270);
			canvas.translate(-heightEdge + getPaddingTop(), 0);
			mLeftEdge.setSize(heightEdge, widthEdge);
			needsInvalidate |= mLeftEdge.draw(canvas);
			canvas.restoreToCount(restoreCount);
		}
		if (!mRightEdge.isFinished()) {
			final int restoreCount = canvas.save();
			final int widthEdge = getWidth();
			final int heightEdge = getHeight() - getPaddingTop() - getPaddingBottom();
			canvas.rotate(90);
			canvas.translate(-getPaddingTop(), -(widthEdge + mMaxScrollX));
			mRightEdge.setSize(heightEdge, widthEdge);
			needsInvalidate |= mRightEdge.draw(canvas);
			canvas.restoreToCount(restoreCount);
		}
		if (needsInvalidate) {
			postInvalidate();
		}
	}

	/** 触摸事件是否拦截的方法 */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		final int action = ev.getAction();
		if (mIsBeingDragged && action == MotionEvent.ACTION_MOVE) {//当已经处于拖动,并且当前事件是MOVE,直接消费掉
			return true;
		}
		switch (action) {
			case MotionEvent.ACTION_DOWN: {
				final float x = ev.getX();
				mLastMotionX = x; //记录住当前的x坐标
				mIsBeingDragged = !mScroller.isFinished();//如果按下的时候还在滚动,则把状态处于拖动状态
				break;
			}
			case MotionEvent.ACTION_MOVE: {
				final float x = ev.getX();
				final int xDiff = (int) Math.abs(x - mLastMotionX);//计算两次的差值
				if (xDiff > mTouchSlop) {//如果大于最小移动的距离,则把状态改变为拖动状态
					mIsBeingDragged = true;
					mLastMotionX = x;
					ViewParent parent = getParent();//并请求父View不要再拦截自己触摸事件,交给自己处理
					if (parent != null) {
						parent.requestDisallowInterceptTouchEvent(true);
					}
				}
				break;
			}
			case MotionEvent.ACTION_CANCEL://当手指离开或者触摸事件取消的时候,把拖动状态取消掉
			case MotionEvent.ACTION_UP:
				mIsBeingDragged = false;
				break;
		}
		return mIsBeingDragged;//如果是拖动状态,则拦截事件,交给自己的onTouch处理
	}

	/** 触摸事件的处理方法 */
	public boolean onTouchEvent(MotionEvent ev) {
		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(ev);
		final int action = ev.getAction();
		switch (action) {
			case MotionEvent.ACTION_DOWN: {//如果是down事件,记录住当前的x坐标
				final float x = ev.getX();
				if (!mScroller.isFinished()) {
					mScroller.abortAnimation();
				}
				mLastMotionX = x;
				break;
			}
			case MotionEvent.ACTION_MOVE: {
				final float x = ev.getX();
				final float deltaX = x - mLastMotionX;
				if (!mIsBeingDragged) {//如果还没有处于拖动,则判断两次的差值是否大于最小拖动的距离
					if (Math.abs(deltaX) > mTouchSlop) {
						mIsBeingDragged = true;
					}
				}
				if (mIsBeingDragged) {//如果处于拖动状态,记录住x坐标
					mLastMotionX = x;
					onMove(deltaX);
				}
				break;
			}
			case MotionEvent.ACTION_UP: {
				if (mIsBeingDragged) {
					final VelocityTracker velocityTracker = mVelocityTracker;
					//先对速度进行一个调整,第一个参数是时间单位,1000毫秒,第二个参数是最大速度。
					velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
					float velocity = velocityTracker.getXVelocity();//获取水平方向上的速度
					onUp(velocity);
				}
			}
			case MotionEvent.ACTION_CANCEL: {
				mIsBeingDragged = false;
				if (mVelocityTracker != null) {
					mVelocityTracker.recycle();
					mVelocityTracker = null;
				}
				break;
			}
		}
		return true;
	}

	private void onMove(float x) {
		if (mMaxScrollX <= 0) {
			if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) {
				mViewPager.fakeDragBy(x);
			}
		} else {
			int scrollByX = -(int) (x + 0.5);
			if (getScrollX() + scrollByX < 0) {
				scrollByX = 0 - getScrollX();
				mLeftEdge.onPull(Math.abs(x) / getWidth());
			}
			if (getScrollX() + scrollByX > mMaxScrollX) {
				scrollByX = mMaxScrollX - getScrollX();
				mRightEdge.onPull(Math.abs(x) / getWidth());
			}
			scrollBy(scrollByX, 0);
			ViewCompat.postInvalidateOnAnimation(this);
		}
	}

	private void onUp(float velocity) {
		if (mMaxScrollX <= 0) {
			if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag();
		} else {
			if (Math.abs(velocity) <= mMinimumVelocity) {
				return;
			}
			mScroller.fling(getScrollX(), 0, -(int) (velocity + 0.5), 0, 0, mMaxScrollX, 0, 0, 270, 0);
			ViewCompat.postInvalidateOnAnimation(this);
		}
	}

	@Override
	public void computeScroll() {
		if (mScroller.computeScrollOffset()) {
			int oldX = mLastScrollX;
			mLastScrollX = mScroller.getCurrX();
			if (mLastScrollX < 0 && oldX >= 0) {
				mLeftEdge.onAbsorb((int) mScroller.getCurrVelocity());
			} else if (mLastScrollX > mMaxScrollX && oldX <= mMaxScrollX) {
				mRightEdge.onAbsorb((int) mScroller.getCurrVelocity());
			}
			int x = mLastScrollX;
			if (mLastScrollX < 0) {
				x = 0;
			} else if (mLastScrollX > mMaxScrollX) {
				x = mMaxScrollX;
			}
			scrollTo(x, 0);
		}
		ViewCompat.postInvalidateOnAnimation(this);
	}

	/** 检测mIndicatorOffset的合法性,并计算出其他有关tab的属性值 */
	private void checkAndcalculate() {
		// 如果指示器起始位置比第一个tab的起始位置还要小,纠正为第一个tab的起始位置,指示器宽度就是第一个tab的宽度
		final View firstTab = getChildAt(0);
		if (mIndicatorLeft < firstTab.getLeft()) {
			mIndicatorLeft = firstTab.getLeft();
			mIndicatorWidth = firstTab.getWidth();
		}
		// 如果指示器起始位置比最后一个tab的起始位置还要大,纠正为最后一个tab的起始位置,指示器宽度就是最后一个tab的宽度
		View lastTab = getChildAt(mTabCount - 1);
		if (mIndicatorLeft > lastTab.getLeft()) {
			mIndicatorLeft = lastTab.getLeft();
			mIndicatorWidth = lastTab.getWidth();
		}
		// 通过指示器的起始位置计算出当前处于第几个position,并且计算出已经偏移了多少,偏移量是以当前所处的tab的宽度的百分比
		for (int i = 0; i < mTabCount; i++) {
			View tab = getChildAt(i);
			if (mIndicatorLeft < tab.getLeft()) {
				mCurrentPosition = i - 1;
				View currentTab = getChildAt(mCurrentPosition);
				mCurrentOffsetPixels = (mIndicatorLeft - currentTab.getLeft()) / (currentTab.getWidth() + 0.0f);
				break;
			}
		}
	}

	/** 滚动到指定的child */
	public void scrollSelf(int position, float offset) {
		if (position >= mTabCount) {
			return;
		}
		final View tab = getChildAt(position);
		mIndicatorLeft = (int) (tab.getLeft() + tab.getWidth() * offset + 0.5);
		int rightPosition = position + 1;
		if (offset > 0 && rightPosition < mTabCount) {
			View rightTab = getChildAt(rightPosition);
			mIndicatorWidth = (int) (tab.getWidth() * (1 - offset) + rightTab.getWidth() * offset + 0.5);
		} else {
			mIndicatorWidth = tab.getWidth();
		}
		checkAndcalculate();

		int newScrollX = position * mSplitScrollX + (int) (offset * mSplitScrollX + 0.5);
		if (newScrollX < 0) {
			newScrollX = 0;
		}
		if (newScrollX > mMaxScrollX) {
			newScrollX = mMaxScrollX;
		}
		//scrollTo(newScrollX, 0);//滑动
		int duration = 100;
		if (mSelectedPosition != -1) {
			duration = (Math.abs(mSelectedPosition - position)) * 100;
		}
		mScroller.startScroll(getScrollX(), 0, (newScrollX - getScrollX()), 0, duration);
		ViewCompat.postInvalidateOnAnimation(this);
	}

	/** 选中指定位置的Tab */
	private void selectTab(int position) {
		for (int i = 0; i < mTabCount; i++) {
			View tab = getChildAt(i);
			if (tab != null) {
				tab.setSelected(position == i);
			}
		}
	}

	/** ViewPager的OnPageChangeListener实现类,因为我们需要在PagerTab中获取PagerView的监听,以便可以调整tab */
	private class PageListener implements OnPageChangeListener {
		@Override
		public void onPageScrolled(int position, float positionOffset, final int positionOffsetPixels) {
			//根据VierPager的偏移值来滚动tab
			scrollSelf(position, positionOffset);
			if (mDelegatePageListener != null) {//这个是提供给外部的
				mDelegatePageListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
			}
		}

		@Override
		public void onPageScrollStateChanged(int state) {
			if (state == ViewPager.SCROLL_STATE_IDLE) {
				mSelectedPosition = -1;
			}
			if (mDelegatePageListener != null) {
				mDelegatePageListener.onPageScrollStateChanged(state);
			}
		}

		@Override
		public void onPageSelected(int position) {
			System.out.println("onPageSelected:" + position);
			mSelectedPosition = position;
			selectTab(position);
			if (mDelegatePageListener != null) {
				mDelegatePageListener.onPageSelected(position);
			}
		}
	}

	/** 如果指示器希望是图片,则继承该接口 */
	public interface IconTabProvider {
		public int getPageIconResId(int position);
		public int getPageSelectedIconResId();
	}
}

一些开发项目常用的工具类,这里不写了,主要有这些:



以上代码只是“电子市场”这类应用的初步搭建,我遇到了一下问题,记录下来,以便学习,分享:

问题一:


java.lang.RuntimeException: 
Unable to start activity 
ComponentInfo{com.example/com.example.MainActivity}: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.


原因分析:
从错误提示中提到Theme.AppCompat theme,这是因为我们的activity一定是继承了兼容包中的类,比如我这里就继续了ActionBarActivity,它来自
android.support.v7.app.ActionBarActivity。所以就要使用与其配合的AppCompat的themecai才行。
解决方法:
  方法一:根据提示来使用了AppCompat的theme。(所有的styles.xml都要改)
  <style name="AppBaseTheme" parent="Theme.AppCompat.Light"></style>
方法二:如果不是那么强烈需要继承自ActionBarActivity,就直接继承Activity吧。

问题二:

空指针异常

一定要在清单文件中配置BaseApplication,否则会发送空指针异常:
<application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        android:name="com.example.application.BaseApplication" >



学习总结:

一、写全局的BaseApplication,继承Application类,并重写父类的oncreate()方法。
  记得在项目清单文件中的application根节点里引用BaseApplication类
public static Application mContext;//全局的上下文
public static Thread mMainThread;//获取主线程
public static Handler mMainThreadHanlder;//获取主线程的handler
public static Looper mMainThreadLopper;//获取主线程Looper
public static int mMainThreadId;//获取到主线程的id
添加get()方法

二、写BaseActivity类,继承ActionBarActivity,并重写父类的oncreate()方法.
记得在values资源文件中的样式文件style.xml中引用样式时,要引用v7包下ActionBar的样式,否则会报错
public abstract void init();//初始化数据
public abstract void initView();//初始化view(布局)
public abstract void initActionBar();//初始化ActionBar
注意:导入v7包,因为要使用ActionBar


三、写MainActivity类,继承BaseActivity类,并重写父类的oncreate()方法,实现里面的抽象方法。
3.0:
引入项目中常用的工具类,已经整理好了,记得时刻收藏好的一些工具类。

其中UIUtils.java工具类中需要使获取前台的activity,这时就需要我们在BaseActivity里面获取,
具体获取方法参考BaseActivity.java源码
3.1:写activity_main.xml布局文件,布局文件是具有侧滑效果的,这里我们引用Android系统下自带的侧滑控件android.support.v4.widget.DrawerLayout
    然后在里面写侧滑的界面和主页面。这里的布局文件中的主页面是一个分页的tab,有tab头和分页页面(自定义控件PagerTab和使用系统自带的ViewPager页面)


侧滑页面使用了帧布局。
四、注意自定义PagerTab,已经写好了,记得整理这些经典的自定义控件,以便提高以后的开发效率。

以上就完成了一个具有侧滑效果的主页。电子市场v1.0


嘿嘿,以上内容只是自己学习整理,方便以后学习,请各路大神赐教。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上善若水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值