重写已被弃用的Gallery

公司以前的Camera项目使用了Gallery,该控件存在问题,有些偶现Bug无法解决。比如 狂点+滑动 会偶现错乱。Gallery原生方法未加锁同步,又不可重写,导致该Bug不可控。

当用户点击又滑动的时候,下面这两个方法就一起调用,偶现Position错乱

    mGalleryView.setOnItemClickListener(new OnItemClickListener());
    mGalleryView.setSelection(mCurrentIndex);

既然这样,那就从新实现有Gallery效果的控件
效果:可以点击切换,也可以外部布局切换。
这里写图片描述

首先实现下图中的自定义textView实现选中缩放效果。

public class AnimaTextView extends TextView
{
    private AnimatorSet scaleTextAnimator;    
    public AnimaTextView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        init();
    }

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

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

    private void init()
    {
        if (this.scaleTextAnimator == null)
        {
          this.scaleTextAnimator = new AnimatorSet();
          ObjectAnimator localObjectAnimator1 = ObjectAnimator.ofFloat(this, "ScaleX", new float[] { 1.0F, 1.05F });
          localObjectAnimator1.setDuration(500);
          ObjectAnimator localObjectAnimator2 = ObjectAnimator.ofFloat(this, "ScaleY", new float[] { 1.0F, 1.05F });
          localObjectAnimator2.setDuration(500);
          this.scaleTextAnimator.play(localObjectAnimator2).with(localObjectAnimator1);
        }
    }

    @Override
    public void setSelected(boolean selected)
    {
        super.setSelected(selected);
        if(selected)
        {
            scaleTextAnimator.start();
        }else
        {
            setScaleX(1.0F);
            setScaleY(1.0F);
        }
    }
}

然后写放置AnimaTextView 的ViewGroup。



public class JScrollParentView extends LinearLayout implements OnClickListener
{

    private AnimaTextView[] mItemView = null;
    private CharSequence[] itemsEntry = null;
    private int mItemSpace = 36;
    private Context mContext = null;
    private int mItemsCount = -1;
    private ColorStateList textColor;
    private float textSize = 14;
    private OnItemSelected mOnItemSelcted = null;
    private TextView mCurrentView = null;
    private int mCurrentPosition = 0;

    public interface OnItemSelected
    {
        void onItemSelected(int position);
    }

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

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

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

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.JScrollParentView);
        itemsEntry = ta.getTextArray(R.styleable.JScrollParentView_item_texts);
        mItemSpace = ta.getDimensionPixelSize(R.styleable.JScrollParentView_item_space, 36);
        textColor = ta.getColorStateList(R.styleable.JScrollParentView_item_texts_colors);
        textSize = ta.getFloat(R.styleable.JScrollParentView_item_texts_size, 12f);
        mItemsCount = itemsEntry.length;
        ta.recycle();
        setOrientation(HORIZONTAL);
        setGravity(Gravity.LEFT);
        setPadding(0, 0, 0, 0);
        mContext = context;      
        initView();
    }
    private void initView()
    {

        if (mItemsCount > 0)
        {
            mItemView = new AnimaTextView[mItemsCount];
            for (int i = 0; i < mItemsCount; i++)
            {
                LayoutParams itemParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
                AnimaTextView item = new AnimaTextView(mContext);
                item.setTextColor(textColor);
                item.setTextSize(textSize);
                item.setText(itemsEntry[i].toString());
                item.setGravity(Gravity.CENTER);
                item.setId(i);
                item.setShadowLayer(1, 0, 0, 0x50000000);
                item.setOnClickListener(this);
               // if(i != 0)
                {
                    itemParams.leftMargin = mItemSpace;
                }
                addView(item,itemParams);
                mItemView[i] = item;
            }
        }
    }

    @Override
    public void onClick(View v)
    {
        if(mOnItemSelcted != null)
        {
            if(mCurrentView != null && mCurrentPosition != v.getId())
            {
                mOnItemSelcted.onItemSelected(v.getId());
            }
        }

    }

    public int getLeftPointX(int position)
    {
        if(position > mItemsCount -1 || mItemsCount <1)
        {
            return 0;
        }
        int paddingLeft = 0;
        for(int i = position; i >= 0; i--)
        {
            int itemWidth = getChildAt(i).getMeasuredWidth(); 
            if( i == position)
            {
                paddingLeft = paddingLeft + itemWidth/2 + mItemSpace; //最后一个是itemWidth/2 + mItemSpace,以后都是itemWidth + mItemSpace
            }else
            {
                paddingLeft = paddingLeft + itemWidth + mItemSpace; 
            }
        }
        return paddingLeft;
    }

    public void setOnItemSelectedListener(OnItemSelected listener)
    {
        mOnItemSelcted = listener;
    }

    public void updateSelcted(int position)
    {

        if(mCurrentView != null)
        {
            mCurrentView.setSelected(false);
        }
        mCurrentView = mItemView[position];
        mCurrentPosition = position;
        mCurrentView.setSelected(true);
    }       
}
public class JScrollPanelLayout extends FrameLayout implements OnItemSelected ,OnGestureListener
{

    private int mLeftStart = 0;
    private JScrollParentView mItemLayout = null;
    private int mCurrentPosition =2;
    private int mItemCount = -1;
    private int mWidth = 0;
    private int mDisplayWith;
    private Context mContext = null;
    private GestureDetector mDetector = null;
    private static final int SLIDE_MIN_PIXCEL = 25;    

    public JScrollPanelLayout(Context context)
    {
        this(context,null);
        // TODO Auto-generated constructor stub
    }

    public JScrollPanelLayout(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        mContext = context;
        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        mDisplayWith = wm.getDefaultDisplay().getWidth();
        mDetector =  new GestureDetector(context,this);
    }

    public JScrollPanelLayout(Context context, AttributeSet attrs)
    {
        this(context, attrs,0);
        // TODO Auto-generated constructor stub
    }

    @Override
    protected void onFinishInflate()
    {
        // TODO Auto-generated method stub
        super.onFinishInflate();
        mItemLayout = (JScrollParentView)findViewById(R.id.scroll_item);
        mItemLayout.setOnItemSelectedListener(this);
        mWidth = getWidth();
        mItemCount = mItemLayout.getChildCount();
        //caculateLeftStart();

    }

    //每次通过动态改变mLeftStart,进行滑动
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom)
    {
        // TODO Auto-generated method stub
        super.onLayout(changed, left, top, right, bottom);
        if(mItemLayout != null)
        {
            mItemLayout.layout(mLeftStart,mItemLayout.getTop(), mLeftStart + mItemLayout.getWidth(), mItemLayout.getBottom());
        }
    }
  //计算mLeftStart ,  mItemLayout.updateSelcted(mCurrentPosition)修改选中View
    public void caculateLeftStart()
    {
        if(mWidth == 0)
        {
            mWidth = mDisplayWith;
        }
        int nextLeftStart = 0;
        if(mItemLayout != null)
        {
            nextLeftStart = mWidth/2 - mItemLayout.getLeftPointX(mCurrentPosition);//确定中心位置
        }
        ValueAnimator anim = ValueAnimator.ofInt(mLeftStart, nextLeftStart);
        anim.setDuration(300);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator animation)
            {
                mLeftStart = (Integer) animation.getAnimatedValue();
                requestLayout();
                mItemLayout.updateSelcted(mCurrentPosition);
            }
        });
        anim.start();
    }

    @Override
    public void onItemSelected(int position)
    {
        if(mCurrentPosition != position)
        {
            mCurrentPosition = position;
            caculateLeftStart();
        }
    }

    @Override
    public boolean onDown(MotionEvent e)
    {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public void onShowPress(MotionEvent e)
    {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e)
    {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
    {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e)
    {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
    {
        doFling(e1,e2,velocityX,velocityY);
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        // TODO Auto-generated method stub
        return mDetector.onTouchEvent(event);
    }
    //e1:手势起点的移动事件
    //e2: 当前手势点的移动事件
    //velocityX:每秒x轴方向移动的像素
    //velocityY: 每秒y轴方向移动的像素
    public void doFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
    {
        if(Math.abs(e1.getX() - e2.getX()) > Math.abs(e1.getY() - e2.getY())){
            if (e1.getX() - e2.getX() > SLIDE_MIN_PIXCEL) {
                if(mCurrentPosition != mItemCount -1)
                {
                    onItemSelected(mCurrentPosition +1);
                }
            } else if (e1.getX() - e2.getX() < -SLIDE_MIN_PIXCEL) {

                if(mCurrentPosition != 0)
                {
                    onItemSelected(mCurrentPosition - 1);
                }
            }
        }
    }
}

使用:

public class CenterIndicatorActivity extends Activity implements OnGestureListener
{

    private JScrollPanelLayout mJScrollPanelLayout;
    private GestureDetector mDetector = null;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.center_indicator_activity);
        mJScrollPanelLayout = (JScrollPanelLayout)findViewById(R.id.scroll_parent);
        mJScrollPanelLayout.postDelayed(new Runnable(){

            @Override
            public void run()
            {
                mJScrollPanelLayout.caculateLeftStart();
                mJScrollPanelLayout.setVisibility(View.VISIBLE);

            }}, 300);
        mDetector = new GestureDetector(this, this);
    }

    @Override
    public boolean onDown(MotionEvent e)
    {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public void onShowPress(MotionEvent e)
    {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e)
    {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
    {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e)
    {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
    {
        mJScrollPanelLayout.doFling(e1, e2, velocityX, velocityY);
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        // TODO Auto-generated method stub
        return mDetector.onTouchEvent(event);
    }
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:jpower="http://schemas.android.com/apk/res/com.jimmy.jpower"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <com.jimmy.jpower.widget.centerIndicator.JScrollPanelLayout
        android:id="@+id/scroll_parent" 
        android:layout_width="match_parent"
        android:layout_height="48dip"
        android:visibility="invisible"
        android:layout_centerInParent="true" 
        android:background="@color/tab_bg">
        <com.ws.jpower.widget.centerIndicator.JScrollParentView
           android:id="@+id/scroll_item" 
           android:layout_width="match_parent"
           android:layout_height="48dip"
           jpower:item_space="18dp"
           jpower:item_texts="@array/jpower_center_list"
           jpower:item_texts_size="14"
           jpower:item_texts_colors="@color/text_color">

        </com.ws.jpower.widget.centerIndicator.JScrollParentView>
    </com.ws.jpower.widget.centerIndicator.JScrollPanelLayout>

</RelativeLayout>
 <array name="jpower_center_list">
        <item>Video</item>
        <item>Photo</item>
        <item>Beauty</item>
        <item>Pano</item>
    </array>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值