标签:
总觉得应该在每一个项目中汲取一点温存。。。哪怕是只有一点点。。。
先看实现的效果图,就是使用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
标签:
原文地址:http://blog.csdn.net/z_zt_t/article/details/51897564