使用ViewPager实现问卷答题效果

总觉得应该在每一个项目中汲取一点温存。。。哪怕是只有一点点。。。
先看实现的效果图,就是使用Viewpager控件进行左右翻页,然后设置边距为负数,进行上一页和下一页的部分显示(设置透明度进行区分),做一个引导的效果,而且重写了Viewpager,主要是为了实现未选定这一页的答案,禁止下一页的滑动。假设你点击了最后一页的答案后自动跳转到结果页面,按照自己设计的权重进行分数显示。这里自定义一个类似进度条的指针显示,是继承了View通过画布绘制出来的效果。

这里写图片描述

这里写图片描述

这里写图片描述

首先我自己对于数据库的理解就是在SQLite Expert Professional 3中编辑新建数据库,然后把那个db文件放到assert资源文件夹中进行访问,因为里面都是一些基础数据。就到网上找了,发现这的是有这么神奇的东西,看来是做后台数据人员习惯了数据库设计的方式,都想这么做。。。我就是这么想的

act_oldtesting.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/login_divider"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/txt_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:background="@drawable/questionnum"
        android:gravity="center"
        android:paddingTop="7dp"
        android:text="3/10"
        android:textColor="@color/white"
        android:textSize="12sp" />

    <LinearLayout
        android:id="@+id/vp_parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:background="@drawable/verificationbg"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/questioncontent"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_marginTop="15dp"
            android:gravity="center_vertical"
            android:paddingLeft="16dp"
            android:text="天冷加衣"
            android:textSize="16sp" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:layout_marginRight="32dp"
            android:layout_marginTop="14dp"
            android:paddingBottom="32dp"
            android:src="@drawable/questionimg" />

        <include
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            layout="@layout/divider_horizontal" />

        <RadioGroup
            android:id="@+id/rap_question"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingBottom="41dp"
            android:paddingLeft="25dp"
            android:paddingRight="25dp"
            android:paddingTop="41dp" >

            <RadioButton
                android:id="@+id/chk_nothave"
                android:layout_width="64dp"
                android:layout_height="32dp"
                android:layout_weight="1"
                android:background="@drawable/selector_nothave"
                android:button="@null"
                android:gravity="center"
                android:text="没有"
                android:textColor="@color/white"
                android:textSize="16sp" />

            <RadioButton
                android:id="@+id/chk_sometimes"
                android:layout_width="64dp"
                android:layout_height="32dp"
                android:layout_marginLeft="25dp"
                android:layout_marginRight="25dp"
                android:layout_weight="1"
                android:background="@drawable/selector_sometimes"
                android:button="@null"
                android:gravity="center"
                android:text="有时"
                android:textColor="@color/white"
                android:textSize="16sp" />

            <RadioButton
                android:id="@+id/chk_usual"
                android:layout_width="64dp"
                android:layout_height="32dp"
                android:layout_weight="1"
                android:background="@drawable/selector_usually"
                android:button="@null"
                android:gravity="center"
                android:text="经常"
                android:textColor="@color/white"
                android:textSize="16sp" />
        </RadioGroup>
    </LinearLayout>

</LinearLayout>

1、题目中的数据来源:自己进行数据库的设计编辑(SQLite Expert Professional 3)建议使用专业版,不要用个人版,然后采用AssetsDatabaseManager类获取assert资源文件目录下的对应db文件。

AssetsDatabaseManager.java

package com.example.db;

import java.io.File;  
import java.io.FileOutputStream;  
import java.io.InputStream;  
import java.io.OutputStream;  
import java.util.HashMap;  
import java.util.Map;  

import android.content.Context;  
import android.content.SharedPreferences;  
import android.content.res.AssetManager;  
import android.database.sqlite.SQLiteDatabase;  
import android.util.Log;  

/** 
 * This is a Assets Database Manager 
 * Use it, you can use a assets database file in you application 
 * It will copy the database file to "/data/data/[your application package name]/database" when you first time you use it 
 * Then you can get a SQLiteDatabase object by the assets database file  
 * @author ZSJ 
 * @time 2016-07-11 
 *  
 *  
 * How to use: 
 * 1. Initialize AssetsDatabaseManager 
 * 2. Get AssetsDatabaseManager 
 * 3. Get a SQLiteDatabase object through database file 
 * 4. Use this database object 
 *  
 * Using example: 
 * AssetsDatabaseManager.initManager(getApplication()); // this method is only need call one time 
 * AssetsDatabaseManager mg = AssetsDatabaseManager.getManager();   // get a AssetsDatabaseManager object 
 * SQLiteDatabase db1 = mg.getDatabase("db1.db");   // get SQLiteDatabase object, db1.db is a file in assets folder 
 * db1.???  // every operate by you want 
 * Of cause, you can use AssetsDatabaseManager.getManager().getDatabase("xx") to get a database when you need use a database 
 */  
public class AssetsDatabaseManager {  
    private static String tag = "AssetsDatabase"; // for LogCat  
    private static String databasepath = "/data/data/%s/databases"; // %s is packageName  


    // A mapping from assets database file to SQLiteDatabase object  
    private Map<String, SQLiteDatabase> databases = new HashMap<String, SQLiteDatabase>();  

    // Context of application  
    private Context context = null;

    // Singleton Pattern  
    private static AssetsDatabaseManager mInstance = null;

    /** 
     * Initialize AssetsDatabaseManager 
     * @param context, context of application 
     */  
    public static void initManager(Context context){  
        if(mInstance == null){  
            mInstance = new AssetsDatabaseManager(context);  
        }  
    }  

    /** 
     * Get a AssetsDatabaseManager object 
     * @return, if success return a AssetsDatabaseManager object, else return null 
     */  
    public static AssetsDatabaseManager getManager(){  
        return mInstance;  
    }  

    private AssetsDatabaseManager(Context context){  
        this.context = context;  
    }  

    /** 
     * Get a assets database, if this database is opened this method is only return a copy of the opened database 
     * @param dbfile, the assets file which will be opened for a database 
     * @return, if success it return a SQLiteDatabase object else return null 
     */  
    public SQLiteDatabase getDatabase(String dbfile) {  
        if(databases.get(dbfile) != null){  
            Log.i(tag, String.format("Return a database copy of %s", dbfile));  
            return (SQLiteDatabase) databases.get(dbfile);  
        }  
        if(context==null)  
            return null;  

        Log.i(tag, String.format("Create database %s", dbfile));  
        String spath = getDatabaseFilepath();  
        String sfile = getDatabaseFile(dbfile);  

        File file = new File(sfile);  
        SharedPreferences dbs = context.getSharedPreferences(AssetsDatabaseManager.class.toString(), 0);  
        boolean flag = dbs.getBoolean(dbfile, false); // Get Database file flag, if true means this database file was copied and valid  
        if(!flag || !file.exists()){  
            file = new File(spath);  
            if(!file.exists() && !file.mkdirs()){  
                Log.i(tag, "Create \""+spath+"\" fail!");  
                return null;  
            }  
            if(!copyAssetsToFilesystem(dbfile, sfile)){  
                Log.i(tag, String.format("Copy %s to %s fail!", dbfile, sfile));  
                return null;  
            }  

            dbs.edit().putBoolean(dbfile, true).commit();  
        }  

        SQLiteDatabase db = SQLiteDatabase.openDatabase(sfile, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);  
        if(db != null){  
            databases.put(dbfile, db);  
        }  
        return db;  
    }  

    private String getDatabaseFilepath(){  
        return String.format(databasepath, context.getApplicationInfo().packageName);  
    }  

    private String getDatabaseFile(String dbfile){  
        return getDatabaseFilepath()+"/"+dbfile;  
    }  

    private boolean copyAssetsToFilesystem(String assetsSrc, String des){  
        Log.i(tag, "Copy "+assetsSrc+" to "+des);  
        InputStream istream = null;  
        OutputStream ostream = null;  
        try{  
            AssetManager am = context.getAssets();  
            istream = am.open(assetsSrc);  
            ostream = new FileOutputStream(des);  
            byte[] buffer = new byte[1024];  
            int length;  
            while ((length = istream.read(buffer))>0){  
                ostream.write(buffer, 0, length);  
            }  
            istream.close();  
            ostream.close();  
        }  
        catch(Exception e){  
            e.printStackTrace();  
            try{  
                if(istream!=null)  
                    istream.close();  
                if(ostream!=null)  
                    ostream.close();  
            }  
            catch(Exception ee){  
                ee.printStackTrace();  
            }  
            return false;  
        }  
        return true;  
    }  

    /** 
     * Close assets database 
     * @param dbfile, the assets file which will be closed soon 
     * @return, the status of this operating 
     */  
    public boolean closeDatabase(String dbfile){  
        if(databases.get(dbfile) != null){  
            SQLiteDatabase db = (SQLiteDatabase) databases.get(dbfile);  
            db.close();  
            databases.remove(dbfile);  
            return true;  
        }  
        return false;  
    }  

    /** 
     * Close all assets database 
     */  
    static public void closeAllDatabase(){  
        Log.i(tag, "closeAllDatabase");  
        if(mInstance != null){  
            for(int i=0; i<mInstance.databases.size(); ++i){  
                if(mInstance.databases.get(i)!=null){  
                    mInstance.databases.get(i).close();  
                }  
            }  
            mInstance.databases.clear();  
        }  
    }  
}  

大概就是到assert中读取db文件,获取到那个db对象,然后封装DBManager这个工具类
DBManager.java

package com.example.db;
import android.app.Application;
import android.database.sqlite.SQLiteDatabase;

public class DBManager {

    public static SQLiteDatabase getdb(Application mApplication) {
        // 初始化,只需要调用一次
        AssetsDatabaseManager.initManager(mApplication);
        // 获取管理对象,因为数据库需要通过管理对象才能够获取
        AssetsDatabaseManager mg = AssetsDatabaseManager.getManager();
        // 通过管理对象获取数据库
        SQLiteDatabase db = mg.getDatabase("test_questions.db");
        return db;
    }

}

2、主要的核心代码Activity文件

MyOldtestAct.java中的代码

package com.example.viewpagerdemo;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;

import com.example.adapter.VPAdapter;
import com.example.db.DBManager;
import com.example.model.Questions;
import com.example.view.MyViewPager;

public class MyOldtestAct extends Activity implements OnClickListener {
    private ImageView btnBack;
    private MyViewPager viewPager;
    // 存放子项view
    private List<View> viewItems = new ArrayList<View>();
    // adapter
    private VPAdapter viewpagerAdpter;
    // 定义问题的集合
    List<Questions> questionsList;
    private List<String> questionList;
    private LinearLayout mViewpagef;
    private LinearLayout vpLinparentnow; // 当前的viewpager嵌套在外层的linerlayout
    private LinearLayout vpLinparentnext; // 下一个的viewpager嵌套在外层的linerlayout
    private LinearLayout vpLinparenttop; // 上一个的viewpager嵌套在外层的linerlayout

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_oldtest);
        setView();
        initData();
    }

    protected void setView() {
        mViewpagef = (LinearLayout) findViewById(R.id.vpfather);
        btnBack = (ImageView) findViewById(R.id.btn_back);
        viewPager = (MyViewPager) findViewById(R.id.vote_submit_viewpager);
        btnBack.setOnClickListener(this);
        for (int i = 0; i < 10; i++) {
            viewItems.add(getLayoutInflater().inflate(R.layout.act_oldtesting,
                    null));
        }
        // 第一次进入的时候不执行该方法,设置透明度
        vpLinparentnext = (LinearLayout) viewItems.get(1).findViewById(
                R.id.vp_parent);
        vpLinparentnext.setAlpha(0.5f);// 初始化的时候默认把第二页透明度设置为0.5
    }

    protected void initData() {
        // 获取数据库
        SQLiteDatabase db = DBManager.getdb(getApplication());
        questionsList = new ArrayList<Questions>();
        questionList = new ArrayList<String>();
        // 把数据库的数据查询出来
        Cursor cursor = db.query("test_bank", null, null, null, null, null,
                null);
        while (cursor.moveToNext()) {
            String questionId = cursor.getString(0);
            String test_cotent = cursor.getString(1);
            Questions Q = new Questions(questionId, test_cotent);
            questionsList.add(Q);
        }
        // 在1-5产生一个随机数,sqlite中有5组题库
        Random rand = new Random();
        int randNum = rand.nextInt(5) + 1;
        Log.w("randNum", String.valueOf(randNum));
        // 根据产生的随机数获取题目
        switch (randNum) {
        case 1:
            for (int i = 1; i <= 10; i++) {
                questionList.add(i + "、"
                        + questionsList.get(i - 1).getTest_cotent());
            }
            break;
        case 2:
            for (int i = 1; i <= 10; i++) {
                questionList.add(i + "、"
                        + questionsList.get(i + 9).getTest_cotent());
            }
            break;
        case 3:
            for (int i = 1; i <= 10; i++) {
                questionList.add(i + "、"
                        + questionsList.get(i + 19).getTest_cotent());
            }
            break;
        case 4:
            for (int i = 1; i <= 10; i++) {
                questionList.add(i + "、"
                        + questionsList.get(i + 29).getTest_cotent());
            }
            break;
        case 5:
            for (int i = 1; i <= 10; i++) {
                questionList.add(i + "、"
                        + questionsList.get(i + 39).getTest_cotent());
            }
            break;
        }
        viewpagerAdpter = new VPAdapter(this, viewItems, questionList);
        viewPager.setOffscreenPageLimit(3);// viewPager设置缓存的页面数
        viewPager.setPageMargin(-20);// 设置2张图之前的间距,-20就是会有边距的效果
        MyOnPageChangeListener myOnPageChangeListener = new MyOnPageChangeListener();
        viewPager.setOnPageChangeListener(myOnPageChangeListener);
        viewPager.setAdapter(viewpagerAdpter);
    }

    public class MyOnPageChangeListener implements OnPageChangeListener {
        @Override
        public void onPageSelected(int position) {
            vpLinparentnow = (LinearLayout) viewItems.get(position)
                    .findViewById(R.id.vp_parent);
            vpLinparentnow.setAlpha(1f); // 设置当前的alpha为1
            if (position == 0) {
                vpLinparentnext = (LinearLayout) viewItems.get(position + 1)
                        .findViewById(R.id.vp_parent);
                vpLinparentnext.setAlpha(0.5f);
            } else if (position == viewItems.size() - 1) {
                vpLinparenttop = (LinearLayout) viewItems.get(position - 1)
                        .findViewById(R.id.vp_parent);
                vpLinparenttop.setAlpha(0.5f);
            } else {
                vpLinparentnext = (LinearLayout) viewItems.get(position + 1)
                        .findViewById(R.id.vp_parent);
                vpLinparenttop = (LinearLayout) viewItems.get(position - 1)
                        .findViewById(R.id.vp_parent);
                vpLinparentnext.setAlpha(0.5f);
                vpLinparenttop.setAlpha(0.5f);
            }
            // 判断当前的选项是否有选中的
            RadioButton chkNothave = (RadioButton) viewItems.get(position)
                    .findViewById(R.id.chk_nothave);
            RadioButton chkSometimes = (RadioButton) viewItems.get(position)
                    .findViewById(R.id.chk_sometimes);
            RadioButton chkUsual = (RadioButton) viewItems.get(position)
                    .findViewById(R.id.chk_usual);
            // 如果当前有选中的项,则可以滑动
            if (chkNothave.isChecked() || chkSometimes.isChecked()
                    || chkUsual.isChecked()) {
                viewPager.isCompleteable(true);
            } else {
                viewPager.isCompleteable(false);
            }
        }

        // 做刷新操作,不然View会重叠有重影
        @Override
        public void onPageScrolled(int position, float positionOffset,
                int positionOffsetPixels) {
            // to refresh frameLayout
            if (mViewpagef != null) {
                mViewpagef.invalidate();
            }
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {

        }
    }

    /**
     * @param index
     *  根据索引值切换页面
     */
    public void setCurrentView(int index) {
        viewPager.setCurrentItem(index);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btn_back:
            finish();
            break;
        }
    }

}

3、MyViewpager自定义的Viewpager,传入Boolean进行上下滑页的控制。(细节)

package com.example.view;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;

/**
 * @author zsj 重写ViewPager禁止其左右滑动
 */
public class MyViewPager extends ViewPager {

    private float x;
    private float mLastMotionX;
    private boolean isComplete = false;

    public void isCompleteable(boolean iscomplete) {
        this.isComplete = iscomplete;
    }

    public MyViewPager(Context context) {
        super(context);
    }

    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent arg0) {
        return super.onTouchEvent(arg0);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            x = ev.getX(); // 在手指按下的时获取X轴的坐标
            break;
        case MotionEvent.ACTION_MOVE:
            mLastMotionX = ev.getX() - x; // 滑动的距离
            if (!isComplete) {
                if (mLastMotionX < 0) {
                    return false;  //不可以滑动
                }
            }
            break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent arg0) {
        return super.onInterceptTouchEvent(arg0);
    }

}

4、对了,还有自定义的PagerAdapter

VPAdapter.java

package com.example.adapter;

import java.util.List;

import com.example.viewpagerdemo.MyOldtestAct;
import com.example.viewpagerdemo.R;
import com.example.viewpagerdemo.TestresultAct;

import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;

public class VPAdapter extends PagerAdapter {
    // 传递过来的页面view的集合
    private List<View> viewItems;
    // 每个item的页面view
    private View convertView;
    private MyOldtestAct mContext = null;
    private List<String> dataItems;
    ViewHolder holder = null;
    int[] mycount = new int[10];

    // 构造方法
    public VPAdapter(MyOldtestAct context, List<View> viewItems,
            List<String> dataItems) {
        this.mContext = context;
        this.viewItems = viewItems;
        this.dataItems = dataItems;
    }

    // 获取总数
    @Override
    public int getCount() {
        return viewItems.size();
    }

    // 官方推荐这么写
    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return arg0 == arg1;
    }

    // 移除页卡
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(viewItems.get(position));
    }

    // 这里返回View
    @Override
    public Object instantiateItem(ViewGroup container, final int position) {
        // 初始化viewholder
        holder = new ViewHolder();
        // 取到每一个子项,进行赋值
        convertView = viewItems.get(position);
        holder.rapQuestion = (RadioGroup) convertView
                .findViewById(R.id.rap_question);
        holder.questionContent = (TextView) convertView
                .findViewById(R.id.questioncontent);
        holder.txtTitle = (TextView) convertView.findViewById(R.id.txt_title);
        holder.questionContent.setText(dataItems.get(position));
        holder.txtTitle.setText(position + 1 + "/10");
        // 监听RadioGrop的选中事件
        holder.rapQuestion
                .setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(RadioGroup group, int checkedId) {
                        if (position != viewItems.size() - 1) {
                            mContext.setCurrentView(position + 1);
                        }// 点击默认跳转到下一页
                        switch (checkedId) {
                        case R.id.chk_nothave:
                            mycount[position] = 10;// 对应的分数值
                            break;
                        case R.id.chk_sometimes:
                            mycount[position] = 5;
                            break;
                        case R.id.chk_usual:
                            mycount[position] = 1;
                            break;
                        }
                        if (position == viewItems.size() - 1) {
                            /*
                             * 统计分数
                             */
                            int num = 0;
                for (int i = 0; i < mycount.length; i++) {
                                num = num + mycount[i];
                            }
// 跳转到测试结果页面
Intent myintent = new Intent(mContext,TestresultAct.class);
myintent.putExtra("num", String.valueOf(num));
                            mContext.startActivity(myintent);
                            mContext.finish();
                        }
                    }
                });
        container.addView(convertView);// 添加页卡
        return convertView; // 返回的是View对象进行显示
    }

    // ViewHolder控件容器
    class ViewHolder {
        RadioGroup rapQuestion;
        TextView questionContent;
        TextView txtTopnum;
        TextView txtBottomnum;
        TextView txtTitle;
    }

}

5、还有就是自定义的PointerProgressBar

package com.example.view;

import com.example.viewpagerdemo.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class PointerProgressBar extends View {
    private int start;

    // 构造方法,带有attrs自定义属性
    public PointerProgressBar(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        paint = new Paint();
        TypedArray mTypeArray = context.obtainStyledAttributes(attrs,
                R.styleable.RoundProgressBar);
        // 获取自定义属性和默认值
        roundColor = mTypeArray.getColor(
                R.styleable.RoundProgressBar_roundColor, Color.GRAY);
        roundProgressColor = mTypeArray.getColor(
                R.styleable.RoundProgressBar_roundProgressColor, Color.RED);
        textColor = mTypeArray.getColor(R.styleable.RoundProgressBar_textColor,
                Color.WHITE);
        textSize = mTypeArray.getDimension(
                R.styleable.RoundProgressBar_textSize, 15);
        roundWidth = mTypeArray.getDimension(
                R.styleable.RoundProgressBar_roundWidth, 5);
        max = mTypeArray.getInteger(R.styleable.RoundProgressBar_max, 100);
        innerRadius = mTypeArray.getDimension(
                R.styleable.RoundProgressBar_innerRadius, 30);
        innerColor = mTypeArray.getColor(
                R.styleable.RoundProgressBar_innerColor, Color.BLUE);
        pointerAngle = mTypeArray.getInteger(
                R.styleable.RoundProgressBar_pointerAngle, 15);
        mTypeArray.recycle();
    }

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

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

    /**
     * 画笔
     */
    private Paint paint;

    /**
     * 内圆半径
     */
    private float innerRadius;

    /**
     * 内圆颜色
     */
    private int innerColor;

    /**
     * 指针偏角
     */
    private int pointerAngle;

    /**
     * 圆环的颜色
     */
    private int roundColor;

    /**
     * 圆环进度的颜色
     */
    private int roundProgressColor;

    /**
     * 中间进度百分比的字符串颜色
     */
    private int textColor;

    /**
     * 中间进度百分比的字符串大小
     */
    private float textSize;

    /**
     * 圆环的宽度
     */
    private float roundWidth;

    /**
     * 最大进度
     */
    private int max;

    /**
     * 当前进度
     */
    private int progress;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        start++;
        /**
         * 画最外层的空心半圆弧
         */
        int center = getWidth() / 2;
        int radius = (int) (center - roundWidth / 2);// 半径
        paint.setColor(roundColor);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(roundWidth);// 圆弧边线宽度
        paint.setAntiAlias(true); // 圆弧抗锯齿
        RectF oval = new RectF(center - radius, center - radius, center
                + radius, center + radius);// 指定圆弧的外轮廓矩形区域
        canvas.drawArc(oval, -180, 180, false, paint);
        /**
         * 画中间的圆心圆
         */
        paint.setStrokeWidth(0);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(innerColor);
        canvas.drawCircle(center, center, innerRadius, paint);
        /**
         * 计算各点坐标
         */
        float angle = (float) (start * 18 / 10);// 需求是从-90~90度刚好旋转了180度
        float cos = (float) Math.cos(Math.PI * angle / 180), sin = (float) Math
                .sin(Math.PI * angle / 180);
        float startX = center - center * cos, startY = center - center * sin;
        float cos1 = (float) Math.cos(Math.PI * (angle + pointerAngle) / 180);
        float sin1 = (float) Math.sin(Math.PI * (angle + pointerAngle) / 180);
        float end1X = center - innerRadius * cos1, end1Y = center - innerRadius
                * sin1;
        float cos2 = (float) Math.cos(Math.PI * (angle - pointerAngle) / 180);
        float sin2 = (float) Math.sin(Math.PI * (angle - pointerAngle) / 180);
        float end2X = center - innerRadius * cos2, end2Y = center - innerRadius
                * sin2;
        Log.e("start ", "angle =" + angle + ",sin = " + sin + ",cos = " + cos
                + ",x=" + startX + ",y=" + startY);
        /**
         * 画圆环进度
         */
        paint.setColor(roundColor);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(roundWidth);
        paint.setColor(roundProgressColor);
        canvas.drawArc(oval, -180, angle, false, paint);
        /**
         * 画指针
         */
        paint.setColor(innerColor);
        paint.setStrokeWidth(0);
        paint.setStyle(Paint.Style.FILL);
        Path path = new Path();
        path.moveTo(startX, startY);
        path.lineTo(end1X, end1Y);
        path.lineTo(end2X, end2Y);
        path.close();
        canvas.drawPath(path, paint);
        /**
         * 画文本进度
         */
        paint.setStrokeWidth(0);
        paint.setColor(textColor);
        paint.setTextSize(textSize);
        paint.setTypeface(Typeface.DEFAULT_BOLD);
        float textWidth = paint.measureText(start + "");
        canvas.drawText(start + "", center - textWidth / 2, center + textSize
                / 2, paint);
        if (start < (int) (((float) progress / (float) max) * 100))
            invalidate();// 不断做刷新操作
    }

    public float getInnerRadius() {
        return innerRadius;
    }

    public void setInnerRadius(float innerRadius) {
        this.innerRadius = innerRadius;
    }

    public int getRoundColor() {
        return roundColor;
    }

    public void setRoundColor(int roundColor) {
        this.roundColor = roundColor;
    }

    public int getRoundProgressColor() {
        return roundProgressColor;
    }

    public void setRoundProgressColor(int roundProgressColor) {
        this.roundProgressColor = roundProgressColor;
    }

    public int getTextColor() {
        return textColor;
    }

    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }

    public float getTextSize() {
        return textSize;
    }

    public void setTextSize(float textSize) {
        this.textSize = textSize;
    }

    public float getRoundWidth() {
        return roundWidth;
    }

    public void setRoundWidth(float roundWidth) {
        this.roundWidth = roundWidth;
    }

    public synchronized int getMax() {
        return max;
    }

    public synchronized void setMax(int max) {
        if (max < 0)
            throw new IllegalArgumentException("max not less than 0");
        this.max = max;
    }

    public synchronized int getProgress() {
        return progress;
    }

    public synchronized void setProgress(int progress) {
        if (max < 0)
            throw new IllegalArgumentException("progress not less than 0");
        if (progress > max)
            progress = max;
        if (progress <= max) {
            this.progress = progress;
            postInvalidate();
        }
    }

    public int getInnerColor() {
        return innerColor;
    }

    public void setInnerColor(int innerColor) {
        this.innerColor = innerColor;
    }

}

大概就是这样了,我觉得问题的思路以及导火索就是使用惯了Sqlserver数据库,一般数据库分析操作都在里面,然后就想着能这么操纵Sqlite数据库,紧接着,PagerAdapter中传入一组View的集合,instantiateItem方法中就是返回了一个View的对象,比普通适配器多的是多了一个ViewGroup,顾名思义,就是一个View的容器,实例化后add进去了。然后就是美工需要的效果,相邻页面需要部分显示,并设置透明度进行区分,还有就是未答题就提交的情况,规定了当前题目未作答的情况下不可翻页,这就引入了需要重写Viewpager中的事件分发的方法dispatchTouchEvent,传入Boolean值进行控制是否可以滑动。总得来说,实现地比较流畅,但是又很多细节是自己需要注意的。合理的需求是锻炼,不合理的需求是磨练啊。。。回头看看,所有的磨练都是锻炼。。。那么继续锻炼。。。

忘记附上demo下载链接了:http://download.csdn.net/detail/z_zt_t/9575012

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用ViewPager实现轮播图的步骤如下: 1. 在布局文件中添加ViewPager控件和指示器(可选)。 ```xml <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="200dp" /> <LinearLayout android:id="@+id/indicator_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="horizontal" /> ``` 2. 创建一个PagerAdapter,设置数据源和页面布局。 ```java public class MyPagerAdapter extends PagerAdapter { private List<Integer> mData; private LayoutInflater mInflater; public MyPagerAdapter(Context context, List<Integer> data) { mData = data; mInflater = LayoutInflater.from(context); } @Override public int getCount() { return mData.size(); } @Override public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { return view == object; } @NonNull @Override public Object instantiateItem(@NonNull ViewGroup container, int position) { View view = mInflater.inflate(R.layout.item_pager, container, false); ImageView imageView = view.findViewById(R.id.image_view); imageView.setImageResource(mData.get(position)); container.addView(view); return view; } @Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { container.removeView((View) object); } } ``` 3. 绑定PagerAdapter和ViewPager,并设置ViewPager的滑动监听,以便更新指示器。 ```java ViewPager viewPager = findViewById(R.id.view_pager); MyPagerAdapter adapter = new MyPagerAdapter(this, mData); viewPager.setAdapter(adapter); LinearLayout indicatorLayout = findViewById(R.id.indicator_layout); for (int i = 0; i < mData.size(); i++) { View indicator = new View(this); int size = getResources().getDimensionPixelSize(R.dimen.indicator_size); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(size, size); lp.leftMargin = i == 0 ? 0 : getResources().getDimensionPixelSize(R.dimen.indicator_margin); indicator.setLayoutParams(lp); indicator.setBackgroundResource(R.drawable.indicator_bg); indicatorLayout.addView(indicator); } viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { super.onPageSelected(position); for (int i = 0; i < mData.size(); i++) { View indicator = indicatorLayout.getChildAt(i); indicator.setSelected(i == position); } } }); ``` 其中,item_pager布局文件中只包含一个ImageView控件,用于显示图片。indicator_bg是指示器的背景,可以自定义。 以上就是使用ViewPager实现轮播图的主要步骤。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值