设为首页 加入收藏

TOP

Android 自定义控件 轻松实现360软件详情页(二)
2015-02-25 16:15:22 来源: 作者: 【 】 浏览:69
Tags:Android 定义 控件 轻松 实现 360 软件 详情
? ? ? ? ? android:layout_height="50dp"
? ? ? ? ? ? android:background="#ffffffff"
? ? ? ? ? ? android:gravity="center" >
? ? ? ?
?//省略了无数控件
? ?



没撒说的 ,let's go 。?


public class StickyNavLayout extends LinearLayout
{


?private View mTop;
?private View mNav;
?private ViewPager mViewPager;
?
?private int mTopViewHeight;
?private ScrollView mInnerScrollView;
?private boolean isTopHidden = false;


?private OverScroller mScroller;
?private VelocityTracker mVelocityTracker;
?private int mTouchSlop;
?private int mMaximumVelocity, mMinimumVelocity;
?
?private float mLastY;
?private boolean mDragging;
?
?


?public StickyNavLayout(Context context, AttributeSet attrs)
?{
? super(context, attrs);
? setOrientation(LinearLayout.VERTICAL);


? mScroller = new OverScroller(context);
? mVelocityTracker = VelocityTracker.obtain();
? mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
? mMaximumVelocity = ViewConfiguration.get(context)
? ? .getScaledMaximumFlingVelocity();
? mMinimumVelocity = ViewConfiguration.get(context)
? ? .getScaledMinimumFlingVelocity();


?}


?@Override
?protected void onFinishInflate()
?{
? super.onFinishInflate();
? mTop = findViewById(R.id.id_stickynavlayout_topview);
? mNav = findViewById(R.id.id_stickynavlayout_indicator);
? View view = findViewById(R.id.id_stickynavlayout_viewpager);
? if (!(view instanceof ViewPager))
? {
? ?throw new RuntimeException(
? ? ?"id_stickynavlayout_viewpager show used by ViewPager !");
? }
? mViewPager = (ViewPager) view;
?}


ok,首先看下成员变量,和我们的变量的初始化,mTop、mNav、mViewPager代表我们布局的三大块了,初始化在onFinishInflate中完成,可以看到直接通过我们的id资源读取就ok。接下来还有些mScroller、mVelocityTracker、mTouchSlop、mMaximumVelocity、mMinimumVelocity、mLastY、mDragging,不用说大家都能想到这是和移动相关的,OverScroller是个辅助类,用于自定移动时帮我们处理掉数学的计算部分。mVelocityTracker相关几个变量,当然是计算什么时候需要自动移动;mTouchSlop帮我区别用户是点击还是拖拽。android中封装了很多常量在ViewConfiguration中,大家有兴趣可以了解他,之所以使用这些常量不仅仅是说,省的我们自己去定义,而是为了和系统的行为保持一致。


看完了构造以后,由于我们使用的是LinearLayout,直接setOrientation(LinearLayout.VERTICAL);也就不必去layout了,控件都自定垂直排列了。那么我们在onMeasure中还需要做些处理??


@Override
?protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
?{
? super.onMeasure(widthMeasureSpec, heightMeasureSpec);
? ViewGroup.LayoutParams params = mViewPager.getLayoutParams();
? params.height = getMeasuredHeight() - mNav.getMeasuredHeight();
?}


?@Override
?protected void onSizeChanged(int w, int h, int oldw, int oldh)
?{
? super.onSizeChanged(w, h, oldw, oldh);
? mTopViewHeight = mTop.getMeasuredHeight();
?}


主要是去设置ViewPager的高度,给它一个固定值,ViewPager自己在测量自己的时候,你要是不给它固定值,可能测量结果与你的预期会差距很大。比如你给它设置个WRAP_CONTENT,你希望他去计算孩子的高度去设置自己的,那么你就想多了。大家可以看下ViewPager测量的源码:


可以看到,对于AT_MOST和EXACTLY两种模式,都是直接读取父类的传入的测量值,也就是说,他不会去测量自己孩子的高度。然后如果模式是:UNSPECIFIED,那么高度直接为0呢。这里大家如果做过这个例子,应该能遇到这种情况,ScrollView中放ViewPager时,测量模式就是UNSPECIFIED,那么Vp直接不显示,原因就在这里。


扯远了,回来,我们继续。


我们设置为Vp的值以后,理论上来说,我们的显示已经正常了,控件都按照我们的预期显示了,但是,但是什么呢?我们现在在自定义的LinearLayout,那么移动是不是应该我们自己去写。


移动的代码很简单,想必大家都知道,直接拿到dx,然后scrollBy就行了。


?@Override
?public boolean onTouchEvent(MotionEvent event)
?{
? mVelocityTracker.addMovement(event);
? int action = event.getAction();
? float y = event.getY();


? switch (action)
? {
? case MotionEvent.ACTION_DOWN:
? ?if (!mScroller.isFinished())
? ? mScroller.abortAnimation();
? ?mVelocityTracker.clear();
? ?mVelocityTracker.addMovement(

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Android 属性动画(Property Anima.. 下一篇Android 教你打造炫酷的ViewPager..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: