[lottery] 07_双色球选号(一)——选中左右位移动画

Android 4.0

双色球选号(一)

一、双色球选号工作
1、Layout文件加载(分析布局)、初始化、设置监听
2、改变标题显示(未获取到信息时默认标题显示)
3、自定义选号adapter
4、选号容器监听
①改变球的背景图片
②给选中的球加动画效果
③增加已选号码的容器
④判断当前点击号码是否包含在该容器中,包含则删除,不包含则添加
⑤快速完成蓝球相关内容
5、选号提示
①红球、蓝球选号
②注数和钱数提示(注数计算factorial)
6、处理机选(手机传感器)
7、定义玩法接口
①清空选号
②添加选号到购物车
③判断当前期信息获取情况
技术点:1、GridView布局
android:columnWidth="35dip" 列宽
android:listSelector="@android:color/white"  选中的时候的背景
android:numColumns="auto_fit" 自动适应屏幕的宽度来决定列数目
2、不同的界面之间传递数据,使用Bundle
由于只有一个Activity,所以不能用startActivityForResult(),只能使用Bundle
3、一个Adapter处理多种情况,所以在里面定义成员,根据情况来处理
4、注意:List中移除一个Integer元素
①不能在list.remove(int),这里会根据元素在集合的位置position来删除
listRedSelected.remove(position);//不能使用position,为根据位置position来移除
②要想使用list.remove(object),那么只能将int转成Integer来存储
listRedSelected.remove(pollRedNumberAdapter.getItem(position));
listRedSelected.remove(Integer.valueOf(position));  
5、动画布局:
rate按照sin函数来动:android:interpolator="@android:anim/cycle_interpolator"
更多:加速,减速
http://developer.android.com/guide/topics/resources/animation-resource.html
1、资源布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <!-- 双色球选号 -->
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/ii_lottery_buy_bottom" >
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
            <!-- 红球的选号 -->
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/id_ssq_red_title" >
                <Button
                    android:id="@+id/bt_ssq_random_red"
                    style="@android:style/Widget.Button.Small"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:layout_marginRight="15dip"
                    android:text="@string/is_random_red" />
            </RelativeLayout>
            <!-- 红球选号的容器 -->
            
            <!-- 高度固定:留出一个空行——小屏幕手机 -->
            <GridView
                android:id="@+id/gv_ssq_red_number_container"
                android:layout_width="match_parent"
                android:layout_height="200dip"
                android:layout_marginLeft="5dip"
                android:layout_marginRight="5dip"
                android:layout_marginTop="5dip"
                android:columnWidth="35dip"
                android:listSelector="@android:color/white"
                android:numColumns="auto_fit" >
            </GridView>
            <!-- 蓝球的选号 -->
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/id_ssq_blue_title" >
                <Button
                    android:id="@+id/bt_ssq_random_blue"
                    style="@android:style/Widget.Button.Small"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:layout_marginRight="15dip"
                    android:text="@string/is_random_blue" />
            </RelativeLayout>
            <!-- 蓝球选号 -->
            <GridView
                android:id="@+id/gv_ssq_blue_number_container"
                android:layout_width="match_parent"
                android:layout_height="120dip"
                android:layout_marginLeft="5dip"
                android:layout_marginRight="5dip"
                android:layout_marginTop="5dip"
                android:columnWidth="35dip"
                android:listSelector="@android:color/white"
                android:numColumns="auto_fit" />
        </LinearLayout>
    </ScrollView>
    <!-- 手机摇啊摇 -->
    <LinearLayout
        android:id="@+id/ll_lottery_buy_bottom_zl"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@drawable/id_lottery_phone_shake_bg"
        android:gravity="center_horizontal" >
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/id_lottery_phone_shake" />
    </LinearLayout>
</RelativeLayout>
2、PlaySSq.java
package cn.zengfansheng.lottery.view;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
 
import org.apache.commons.lang3.StringUtils;
 
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.GridView;
import cn.zengfansheng.lottery.ConstantValue;
import cn.zengfansheng.lottery.R;
import cn.zengfansheng.lottery.view.adapter.PollAdapter;
import cn.zengfansheng.lottery.view.manager.TopTitleManager;
 
/**
* 双色球View
*
* @author hacket
*/

public class PlaySSQ extends BaseView {
 
    public PlaySSQ(Context context, Bundle bundle) {// 一定要加上个这个构造函数,否则在changeView反射会出错
        super(context);
        this.bundle = bundle;// FIXME:这里要用bundle记住,否则第一次从购彩大厅进来,标题不会变
    }
 
    @Override
    protected void init() {
        showView = (ViewGroup) View.inflate(context, R.layout.zl_playssq, null);
 
        // 1、组件初始化
        initComponent();
 
        // 3、球选中的集合,这个要放在setSsqAdapter()前面,否则会getView中会报空指针访问异常
        initListSelected();
 
        // 2、设置数据适配器
        setSsqAdapter();
    }
 
    @Override
    protected void setListener() {
 
        // 设置红色监听
        btSsqRandomRed.setOnClickListener(this);
 
        // 设置蓝色监听
        btSsqRandomBlue.setOnClickListener(this);
 
        // 设置点击效果
        setClickAnimation();
    }
 
    @Override
    public int getViewId() {
        return ConstantValue.VIEW_SSQ;
    }
 
    // NOTE 1****************************** 双色球 ******************************
    // ①通用三步:Layout文件加载(分析布局)、初始化、设置监听
    // ②处理标题内容展示:判断在购彩大厅界面是否获取到当前销售期信息
    // ③设置选号容器内容
    // ④选号处理(效果)
    // ⑤处理机选:一注为基准(红球六个,蓝球1)
    // ⑥手机摇晃处理,机选一注
    // ⑦底部导航中间提示信息处理
    // ⑧清空与选好了操作
 
    // ****************************** 1-1、双色球初始化 ******************************
    private GridView gvSsqRedNumber;// 红色双色球布局
    private Button btSsqRandomRed;// 红色球随机生成按钮
 
    private GridView gvSsqBlueNumber;// 蓝色双色球布局
    private Button btSsqRandomBlue;// 蓝色球随机生成按钮
    public void initComponent() {
 
        gvSsqRedNumber = (GridView) findViewById(R.id.gv_ssq_red_number_container);
        btSsqRandomRed = (Button) findViewById(R.id.bt_ssq_random_red);
 
        gvSsqBlueNumber = (GridView) findViewById(R.id.gv_ssq_blue_number_container);
        btSsqRandomBlue = (Button) findViewById(R.id.bt_ssq_random_blue);
 
    }
 
    // NOTE
    // 2******************************1-2、设置监听******************************
 
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.bt_ssq_random_red:// 红色随机
            // :机选红色球
            randomSelectRedBall();
            break;
        case R.id.bt_ssq_random_blue:// 蓝色随机
            // :机选篮色球
            randomSelectBlueBall();
            break;
        }
    }
 
    // FIXME:在购彩大厅切换到双色球,标题没有变,但第二次进来变换了(原因,构造方法中没有记录bundle)
    // NOTE ******2、处理标题内容展示:判断在购彩大厅界面是否获取到当前销售期信息********
    public void handleTitle() {
        // 判断在购彩大厅界面是否获取到当前销售期信息
 
        if (bundle != null) {// 如果获取到期次信息:数据传递
            String title = context.getResources().getString(R.string.is_ssq_title);
            title = StringUtils.replace(title, "ISSUE", bundle.getString("issue"));
            TopTitleManager.getTopTitleManager().changeTopCommonTitle(title);
        } else {// 否则使用默认的标题进行展示
            TopTitleManager.getTopTitleManager().changeTopCommonTitle(R.string.is_ssq_title_default);
        }
    }
 
    // 在切换到界面的时候,进行标题的更新
    @Override
    public void onResume() {
        super.onResume();
        handleTitle();
    }
 
    // NOTE 3************************ 3、设置选号容器内容 ******************
    private PollAdapter pollRedNumberAdapter;// 红色球选号容器
    private PollAdapter pollBlueNumberAdapter;// 蓝色球选号容器
 
    /**
     * 设置选号内容
     */

    public void setSsqAdapter() {
 
        // 红色选号器
        pollRedNumberAdapter = new PollAdapter(context, 33, listRedSelected,R.drawable.id_redball);
        gvSsqRedNumber.setAdapter(pollRedNumberAdapter);
 
        // 蓝色选号器
        pollBlueNumberAdapter = new PollAdapter(context, 1, 16,listBlueSelected,R.drawable.id_blueball);
        gvSsqBlueNumber.setAdapter(pollBlueNumberAdapter);
    }
 
    // ****************************** 4、选号处理(效果) ******************************
    // 1、未选中的话,改变背景颜色,并播放位移动画,加入到一个集合中去
    // 2、选中的话,还原背景颜色,从集合中移除
    private List<Integer> listRedSelected;// 红色球选中的集合
    private List<Integer> listBlueSelected;// 蓝色球选中的集合
 
    public void initListSelected(){
        listRedSelected = new ArrayList<Integer>();
        listBlueSelected = new ArrayList<Integer>();
    }
 
    /**
     * 设置点击选号时候的动画
     */

    public void setClickAnimation() {
        // 红色球
        gvSsqRedNumber.setOnItemClickListener(new OnItemClickListener() {
 
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
 
                // 判断:是否已经被选中
                // 存储用户已经选中的号码
 
                if (listRedSelected.contains(pollRedNumberAdapter
                        .getItem(position))) {// 如果存在集合中,将其还原灰色背景,从集合中移除
                    // 1、如果选中
                    // ①从集合中清除
                    // listRedSelected.remove(position);//不能使用position,为根据位置position来移除
                    //listRedSelected.remove(Integer.valueOf(position));
                    listRedSelected.remove(pollRedNumberAdapter.getItem(position));
                    // ②添加号码到集合中
                    view.setBackgroundResource(R.drawable.id_defalut_ball);
                } else {// 没有存在,加入集合,更改红色背景
                    // 2、如果没有被选中
                    // ①添加号码到集合中
                    listRedSelected.add(position+1);
                    // ②修改背景图片
                    view.setBackgroundResource(R.drawable.id_redball);
                    // ③view需要处理左右摇摆的动画
                    Animation shakeAnimation = AnimationUtils.loadAnimation(context, R.anim.za_ball_shake);
                    view.startAnimation(shakeAnimation);
                }
            }
        });
        gvSsqBlueNumber.setOnItemClickListener(new OnItemClickListener() {
 
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                if (listBlueSelected.contains(position + 1)) {// 如果存在集合中,将其还原灰色背景,从集合中移除
 
                    listBlueSelected.remove(Integer.valueOf(position+1));
                    view.setBackgroundResource(R.drawable.id_defalut_ball);
                } else {// 没有存在,加入集合,更改蓝色背景
 
                    listBlueSelected.add(position+1);
 
                    view.setBackgroundResource(R.drawable.id_blueball);
 
                    Animation shakeAnimation = AnimationUtils.loadAnimation(context, R.anim.za_ball_shake);
                    view.startAnimation(shakeAnimation);
                }
            }
        });
    }
 
    // NOTE ***************** 4、处理机选:一注为基准(红球六个,蓝球1) ***************
 
    /**
     * 机选红球(6个)
     */

    private void randomSelectRedBall(){
        // 机选红球
        // 清空集合,不能重复
        if (listRedSelected != null) {
            listRedSelected.clear();
        }
        Random random = new Random();
        while (listRedSelected.size() < 6) {
            int redBall = random.nextInt(33) + 1;// 不包含0,所以要加1
            if (listRedSelected.contains(redBall)) {// 如果包含了,那么continue
                continue;
            }
            // 更新adapter
            listRedSelected.add(redBall);
        }
        // 由于是随机的选择,所以需要全部去判断下,是否被选择了
        pollRedNumberAdapter.notifyDataSetChanged();
    }
 
    /**
     * 机选蓝球(1个)
     */

    private void randomSelectBlueBall(){
        // 清空集合
        if (listBlueSelected != null) {
            listBlueSelected.clear();
        }
        Random random = new Random();
        int blueBall = random.nextInt(16) + 1;// 不包含0,所以要加1
        listBlueSelected.add(blueBall);
        // 由于是随机的选择,所以需要全部去判断下,是否被选择了
        pollBlueNumberAdapter.notifyDataSetChanged();
    }
}
3、Adapter:PollAdapter.java
package cn.zengfansheng.lottery.view.adapter;
 
import java.text.DecimalFormat;
import java.util.List;
 
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import cn.zengfansheng.lottery.R;
import cn.zengfansheng.lottery.util.DensityUtil;
 
/**
* 选号容器
*
* @author hacket
*/

public class PollAdapter extends BaseAdapter {
 
    /**
     * 上下文
     */

    private Context context;
    /**
     * 球号码开始
     */

    public int startBall;
    /**
     * 球号码结束
     */

    public int endBall;
 
    /**
     * 球选中的集合
     */

    private List<Integer> listSelected;
 
    /**
     * 球选中的时候背景资源的id
     */

    private int selectedBkgResId;
 
    // ***********************构造器
 
    /**
     * @param context
     *            上下文
     * @param endBall
     *            最后一个球号码
     * @param listSelected
     *            选中球和集合
     * @param resId
     *            选中时球的背景资源id
     */

    public PollAdapter(Context context,int endBall,List<Integer> listSelected,int resId) {
        this.context = context;
        this.endBall = endBall;
        this.listSelected = listSelected;
        this.selectedBkgResId = resId;
    }
 
    /**
     * @param context
     *            上下文
     * @param startBall
     *            开始一个球号码
     * @param endBall
     *            最后一个球号码
     * @param listSelected
     *            选中球和集合
     * @param resId
     *            选中时球的背景资源id
     */

    public PollAdapter(Context context,int startBall, int endBall,List<Integer> listSelected,int resId) {
        this.context = context;
        this.startBall = startBall;
        this.endBall = endBall;
        this.listSelected = listSelected;
        this.selectedBkgResId = resId;
    }
 
    // ***********************方法功能
    // 1、球的个数
    @Override
    public int getCount() {
        if (startBall == 0) {
            return endBall;
        } else {
            return endBall - startBall + 1;
        }
    }
 
    // 2、return position + 1;
    @Override
    public Object getItem(int position) {
        return position + 1;
    }
 
    @Override
    public long getItemId(int position) {
        return position;
    }
 
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
 
        TextView tvBall = new TextView(context);
 
        // 格式化球上面的数字
        DecimalFormat df = new DecimalFormat("00");
        String numberBall = df.format(position + 1);
        // 设置文本
        tvBall.setText(numberBall);
        // 居中显示
        tvBall.setGravity(Gravity.CENTER);
        // 设置大小
        int textSize = DensityUtil.dip2px(context, 16);
        tvBall.setTextSize(textSize);
 
        // 设置背景
        if (listSelected.contains(position + 1)) {
            tvBall.setBackgroundResource(selectedBkgResId);
        } else {
            tvBall.setBackgroundResource(R.drawable.id_defalut_ball);
        }
        return tvBall;
    }
 
}
4、结果: