編輯:關於Android編程
總覺得應該在每一個項目中汲取一點溫存。。。哪怕是只有一點點。。。
先看實現的效果圖,就是使用Viewpager控件進行左右翻頁,然後設置邊距為負數,進行上一頁和下一頁的部分顯示(設置透明度進行區分),做一個引導的效果,而且重寫了Viewpager,主要是為了實現未選定這一頁的答案,禁止下一頁的滑動。假設你點擊了最後一頁的答案後自動跳轉到結果頁面,按照自己設計的權重進行分數顯示。這裡自定義一個類似進度條的指針顯示,是繼承了View通過畫布繪制出來的效果。
首先我自己對於數據庫的理解就是在SQLite Expert Professional 3中編輯新建數據庫,然後把那個db文件放到assert資源文件夾中進行訪問,因為裡面都是一些基礎數據。就到網上找了,發現這的是有這麼神奇的東西,看來是做後台數據人員習慣了數據庫設計的方式,都想這麼做。。。我就是這麼想的
act_oldtesting.xml
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 databases = new HashMap();
// 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
大概就是到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 viewItems = new ArrayList();
// adapter
private VPAdapter viewpagerAdpter;
// 定義問題的集合
List questionsList;
private List 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();
questionList = new ArrayList();
// 把數據庫的數據查詢出來
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 viewItems;
// 每個item的頁面view
private View convertView;
private MyOldtestAct mContext = null;
private List dataItems;
ViewHolder holder = null;
int[] mycount = new int[10];
// 構造方法
public VPAdapter(MyOldtestAct context, List viewItems,
List 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值進行控制是否可以滑動。總得來說,實現地比較流暢,但是又很多細節是自己需要注意的。合理的需求是鍛煉,不合理的需求是磨練啊。。。回頭看看,所有的磨練都是鍛煉。。。那麼繼續鍛煉。。。
1. 緩存 名稱 描述 DiskLruCache Java實現基於LRU的磁盤緩存 2.圖片加載 名稱 描述 Android Un
一、 MonkeyRunner簡介monkeyrunner也是一款安卓sdk自有的測試工具,開源,位於\sdk\tools下面,它主要做性能測試,回歸測試,並且可以自定義
Context:我自己寫下Google關於Android性能優化的視頻課程的翻譯,希望轉載者不要刪除我的博客地址http://blog.csdn.net/zhjali12
百度一鍵root是一款很簡單清潔的軟件,很適合剛剛接觸root使用的群眾用。root就是讓你的獲取手機權限,然後處理一些手機系統本來無法處理的軟件,讓你的手
折騰一下午,遇到若干問題:如,設置水平HORIZONTAL時,占用多個跨
SimpleVrPanorama其實這篇應該寫SimpleVrPanor