├── puzzle.iml___jb_bak___
├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── drawable
│ │ │ │ ├── default1.jpg
│ │ │ │ ├── default2.jpg
│ │ │ │ ├── default3.jpg
│ │ │ │ ├── default4.jpg
│ │ │ │ ├── default5.jpg
│ │ │ │ ├── default6.jpg
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── puzzle_en.png
│ │ │ │ ├── ic_arrow_back_white_24dp.png
│ │ │ │ ├── dish_shape_top.xml
│ │ │ │ ├── button_shape_top.xml
│ │ │ │ ├── dish_shape_middle.xml
│ │ │ │ ├── person_shape_top.xml
│ │ │ │ ├── dish_shape_bottom.xml
│ │ │ │ ├── button_shape_bottom.xml
│ │ │ │ ├── person_shape_bottom.xml
│ │ │ │ ├── disappearing.xml
│ │ │ │ ├── person_background.xml
│ │ │ │ ├── button_background.xml
│ │ │ │ ├── appearing.xml
│ │ │ │ └── dish_background.xml
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── again.png
│ │ │ │ ├── back.png
│ │ │ │ ├── denglu.png
│ │ │ │ ├── finish.png
│ │ │ │ ├── help.png
│ │ │ │ ├── input.png
│ │ │ │ ├── lock.png
│ │ │ │ ├── logo.png
│ │ │ │ ├── logoff.png
│ │ │ │ ├── share.png
│ │ │ │ ├── time.png
│ │ │ │ ├── user.png
│ │ │ │ ├── zhuce.png
│ │ │ │ ├── loginbg.png
│ │ │ │ ├── button_exit.png
│ │ │ │ ├── button_rank.png
│ │ │ │ ├── change_pwd.png
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── button_begin.png
│ │ │ │ └── button_setting.png
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values-v21
│ │ │ │ └── styles.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── menu
│ │ │ │ └── menu_user_info.xml
│ │ │ ├── values
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ └── layout
│ │ │ │ ├── choose_pic_gridview_item.xml
│ │ │ │ ├── content_rank.xml
│ │ │ │ ├── toolbar_main.xml
│ │ │ │ ├── game_success.xml
│ │ │ │ ├── activity_main.xml
│ │ │ │ ├── layout_alertdiag.xml
│ │ │ │ ├── layout_record.xml
│ │ │ │ ├── activity_change_pwd.xml
│ │ │ │ ├── content_choose_pic.xml
│ │ │ │ ├── activity_rank.xml
│ │ │ │ ├── activity_setting.xml
│ │ │ │ ├── activity_choose_pic.xml
│ │ │ │ ├── activity_user_info.xml
│ │ │ │ ├── content_game.xml
│ │ │ │ ├── activity_register.xml
│ │ │ │ ├── content_main.xml
│ │ │ │ ├── activity_game.xml
│ │ │ │ ├── activity_login.xml
│ │ │ │ ├── layout_lv_rank.xml
│ │ │ │ ├── content_change_pwd.xml
│ │ │ │ ├── content_setting.xml
│ │ │ │ └── content_user_info.xml
│ │ ├── java
│ │ │ └── studio
│ │ │ │ └── androiddev
│ │ │ │ └── puzzle
│ │ │ │ ├── db
│ │ │ │ └── DBHelper.java
│ │ │ │ ├── event
│ │ │ │ ├── TimeEvent.java
│ │ │ │ ├── GameSuccessEvent.java
│ │ │ │ ├── DishManagerInitFinishEvent.java
│ │ │ │ ├── DishManagerInitStartEvent.java
│ │ │ │ └── PieceMoveSuccessEvent.java
│ │ │ │ ├── utils
│ │ │ │ ├── StaticValue.java
│ │ │ │ ├── RegExUtil.java
│ │ │ │ ├── DensityUtil.java
│ │ │ │ ├── GlobalUtils.java
│ │ │ │ ├── SecurityUtils.java
│ │ │ │ ├── GameTimer.java
│ │ │ │ └── BitmapUtils.java
│ │ │ │ ├── imagesplit
│ │ │ │ ├── ImagePiece.java
│ │ │ │ ├── Uri2FilePath.java
│ │ │ │ └── ImageSplitter.java
│ │ │ │ ├── activity
│ │ │ │ ├── BaseActivity.java
│ │ │ │ ├── ActivityManager.java
│ │ │ │ ├── ChoosePicActivity.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── RegisterActivity.java
│ │ │ │ ├── ChangePwdActivity.java
│ │ │ │ ├── LoginActivity.java
│ │ │ │ ├── SettingActivity.java
│ │ │ │ ├── RankActivity.java
│ │ │ │ ├── GameActivity.java
│ │ │ │ └── UserInfoActivity.java
│ │ │ │ ├── dish
│ │ │ │ ├── DragImageView.java
│ │ │ │ └── DishManager.java
│ │ │ │ ├── PuzzleApplication.java
│ │ │ │ ├── adapter
│ │ │ │ └── ChoosePicGridViewAdapter.java
│ │ │ │ ├── model
│ │ │ │ ├── Record.java
│ │ │ │ └── User.java
│ │ │ │ └── bgm
│ │ │ │ └── MusicServer.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── studio
│ │ │ └── androiddev
│ │ │ └── puzzle
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── studio
│ │ └── androiddev
│ │ └── puzzle
│ │ └── ApplicationTest.java
├── build.gradle
└── proguard-rules.pro
├── settings.gradle
├── .gitignore
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── LICENSE.md
├── README.md
├── gradlew.bat
└── gradlew
/puzzle.iml___jb_bak___:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .DS_Store
5 | /build
6 | /captures
7 | /.idea/
8 | /app/src/main/res/raw/
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/drawable/default1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/drawable/default1.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/default2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/drawable/default2.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/default3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/drawable/default3.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/default4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/drawable/default4.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/default5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/drawable/default5.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/default6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/drawable/default6.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/drawable/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/puzzle_en.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/drawable/puzzle_en.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/again.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/again.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/back.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/denglu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/denglu.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/finish.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/finish.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/help.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/input.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/input.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/lock.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/logo.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/logoff.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/logoff.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/share.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/time.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/time.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/user.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/zhuce.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/zhuce.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/loginbg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/loginbg.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/button_exit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/button_exit.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/button_rank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/button_rank.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/change_pwd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/change_pwd.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/button_begin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/button_begin.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/button_setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/mipmap-xxhdpi/button_setting.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_back_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FreedomZZQ/Puzzle-Android/HEAD/app/src/main/res/drawable/ic_arrow_back_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/db/DBHelper.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.db;
2 |
3 | /**
4 | * Puzzle
5 | * Created by ZQ on 2016/3/24.
6 | */
7 | public class DBHelper {
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/event/TimeEvent.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.event;
2 |
3 | /**
4 | * puzzle
5 | * Created by ZQ on 2016/4/27.
6 | */
7 | public class TimeEvent {
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/event/GameSuccessEvent.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.event;
2 |
3 | /**
4 | * puzzle
5 | * Created by ZQ on 2016/4/17.
6 | */
7 | public class GameSuccessEvent {
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/event/DishManagerInitFinishEvent.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.event;
2 |
3 | /**
4 | * puzzle
5 | * Created by ZQ on 2016/4/19.
6 | */
7 | public class DishManagerInitFinishEvent {
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/event/DishManagerInitStartEvent.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.event;
2 |
3 | /**
4 | * puzzle
5 | * Created by ZQ on 2016/4/19.
6 | */
7 | public class DishManagerInitStartEvent {
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dish_shape_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_shape_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dish_shape_middle.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/person_shape_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dish_shape_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_shape_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/person_shape_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/disappearing.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/person_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/appearing.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/utils/StaticValue.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.utils;
2 |
3 | /**
4 | * Created by lenovo on 2016/3/22.
5 | */
6 | public class StaticValue {
7 | public static String bmobId = "284420dcdca2ba4dbb2f1b2bb463fb35";
8 |
9 | public static final String SP_NAME = "puzzle_sp";
10 | public static final String SP_LEVEL = "level";
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/event/PieceMoveSuccessEvent.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.event;
2 |
3 | /**
4 | * puzzle
5 | * Created by ZQ on 2016/4/17.
6 | */
7 | public class PieceMoveSuccessEvent {
8 |
9 | private int index;
10 | public PieceMoveSuccessEvent(int index){
11 | this.index = index;
12 | }
13 |
14 | public int getIndex(){
15 | return index;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/test/java/studio/androiddev/puzzle/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/studio/androiddev/puzzle/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/imagesplit/ImagePiece.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.imagesplit;
2 |
3 | /**
4 | * Created by Administrator on 2016/3/27.
5 | */
6 | import android.graphics.Bitmap;
7 |
8 | public class ImagePiece {
9 |
10 | public int index = 0;
11 |
12 | public Bitmap bitmap = null;
13 |
14 | public void recycleBitmap(){
15 | if(bitmap != null){
16 | bitmap.recycle();
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_user_info.xml:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 | 20dp
7 |
8 |
9 |
10 | 45dp
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/choose_pic_gridview_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dish_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/activity/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 |
6 | public abstract class BaseActivity extends AppCompatActivity {
7 |
8 | protected static final String TAG = "puzzle";
9 |
10 | @Override
11 | protected void onCreate(Bundle savedInstanceState) {
12 | super.onCreate(savedInstanceState);
13 | ActivityManager.addActivity(this);
14 | }
15 |
16 | @Override
17 | protected void onDestroy() {
18 | super.onDestroy();
19 | ActivityManager.removeActivity(this);
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/utils/RegExUtil.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.utils;
2 |
3 | import java.util.regex.Pattern;
4 |
5 | /**
6 | * Created by lenovo on 2016/3/22.
7 | */
8 | public class RegExUtil {
9 |
10 | //手机号输入验证
11 | public static Boolean confirmPhone(String phone){
12 |
13 | boolean matches = Pattern.matches("^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$", phone);
14 | return matches;
15 | }
16 |
17 | //密码格式要求:长度为8-20的数字,下划线或字母
18 | public static Boolean confirmPwd(String pwd){
19 | //密码长度为8-20的数字,下划线或字母
20 | boolean matches = Pattern.matches("[a-zA-Z_0-9]{8,20}", pwd);
21 | return matches;
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_rank.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Mon Mar 21 22:24:34 CST 2016
16 | systemProp.http.proxyHost=127.0.0.1
17 | systemProp.http.proxyPort=1112
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/toolbar_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/game_success.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/utils/DensityUtil.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.utils;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * puzzle
7 | * Created by ZQ on 2016/4/4.
8 | */
9 | public class DensityUtil {
10 |
11 | /**
12 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
13 | */
14 | public static int dip2px(Context context, float dpValue) {
15 | final float scale = context.getResources().getDisplayMetrics().density;
16 | return (int) (dpValue * scale + 0.5f);
17 | }
18 |
19 | /**
20 | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
21 | */
22 | public static int px2dip(Context context, float pxValue) {
23 | final float scale = context.getResources().getDisplayMetrics().density;
24 | return (int) (pxValue / scale + 0.5f);
25 | }
26 |
27 | public static float getScale(Context context){
28 | return context.getResources().getDisplayMetrics().density;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_alertdiag.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
17 |
18 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #ff9000
4 | #f27d00
5 | #dcdcdc
6 | #60ffffff
7 | #30ffffff
8 | #ff9000
9 | #8ad520
10 | #3383e6
11 | #76a6e3
12 | #eb3219
13 | #f5f5f5
14 | #8d8d8d
15 | #ebebeb
16 | #ffffff
17 | #e0e0e0
18 | #c4c4c4
19 | #e6e6e6
20 | #dcdcdc
21 | #b8b8b8
22 | #737373
23 | #00000000
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 FreedomZZQ & haze & YouJoin Studio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_record.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
22 |
23 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_change_pwd.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_choose_pic.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/activity/ActivityManager.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.activity;
2 |
3 | import android.app.Activity;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | /**
9 | * The manager to manage activities
10 | * Puzzle
11 | * Created by ZQ on 2016/3/24.
12 | */
13 | public class ActivityManager {
14 |
15 | /**
16 | * A list that holds all activities.
17 | */
18 | public static List activities = new ArrayList<>();
19 |
20 | /**
21 | * Add Activity to the list.
22 | * @param activity The Activity you want to add in.
23 | */
24 | public static void addActivity(Activity activity){ activities.add(activity); }
25 |
26 | /**
27 | * Remove Activity from the list.
28 | * @param activity The Activity you want to remove.
29 | */
30 | public static void removeActivity(Activity activity){ activities.remove(activity); }
31 |
32 | /**
33 | * Finish all the activities to finish the app.
34 | */
35 | public static void finishAll(){
36 | for(Activity activity : activities){
37 | if(!activity.isFinishing()){
38 | activity.finish();
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_rank.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_setting.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_choose_pic.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_user_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
17 |
18 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 拼了个图
3 | 设置
4 | 发现
5 | 游戏
6 | 个人中心
7 | 再按一次返回键退出
8 | 修改密码
9 | 00:00
10 | 选择关卡
11 |
12 |
13 |
14 | 难度
15 | 调整游戏难度
16 | 使拼图块数量不同
17 | 关于
18 | 本游戏仅供娱乐学习使用,未经允许不得修改
19 | Power by AndroidPuzzle and YouJoinStudio
20 | 3 X 3
21 | 4 X 4
22 | 5 X 5
23 | 6 X 6
24 | 我最近在玩 拼了个图 觉得不错,推荐你也下载来玩一下~
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/utils/GlobalUtils.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.utils;
2 |
3 | import java.util.Random;
4 |
5 | /**
6 | * Puzzle
7 | * Created by ZQ on 2016/3/24.
8 | */
9 | public class GlobalUtils {
10 |
11 | /**
12 | * 对接收到的json字符串进行处理,去掉可能的垃圾头和垃圾尾,使其符合json格式
13 | * @param jsonString 接收到的json字符串
14 | * @return 处理后的json字符串
15 | */
16 | public static String FixJsonString(String jsonString){
17 |
18 | int startIndex = jsonString.indexOf('{');
19 | int endIndex = jsonString.lastIndexOf('}');
20 |
21 | //LogUtils.d("hehe", jsonString.substring(startIndex, endIndex + 1));
22 | return jsonString.substring(startIndex, endIndex + 1);
23 | }
24 |
25 | /**
26 | *
27 | * @param total
28 | * @return
29 | */
30 | public static int[] getRamdomList(int total){
31 | int[] result = new int[total];
32 | for(int i = 0; i < total; i++){
33 | result[i] = i;
34 | }
35 |
36 | Random random = new Random();
37 | for(int i = 0; i < total; i++){
38 | int p = random.nextInt(total);
39 | int temp = result[i];
40 | result[i] = result[p];
41 | result[p] = temp;
42 | }
43 |
44 | random = null;
45 | return result;
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/dish/DragImageView.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.dish;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.View;
6 | import android.widget.ImageView;
7 |
8 | /**
9 | * puzzle
10 | * Created by ZQ on 2016/4/4.
11 | */
12 | public class DragImageView extends ImageView {
13 |
14 | private int mIndex;
15 |
16 | public DragImageView(Context context) {
17 | super(context);
18 | init(context);
19 | }
20 |
21 | public DragImageView(Context context, AttributeSet attrs) {
22 | super(context, attrs);
23 | init(context);
24 | }
25 |
26 | public DragImageView(Context context, AttributeSet attrs, int defStyleAttr) {
27 | super(context, attrs, defStyleAttr);
28 | init(context);
29 | }
30 |
31 | private void init(Context context) {
32 |
33 | setOnLongClickListener(new OnLongClickListener() {
34 | @Override
35 | public boolean onLongClick(View v) {
36 | v.startDrag(null, new View.DragShadowBuilder(v), mIndex, 0);
37 | return true;
38 | }
39 | });
40 | }
41 |
42 | public void setIndex(int index) {
43 | mIndex = index;
44 | }
45 |
46 | public int getIndex(){
47 | return mIndex;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "studio.androiddev.puzzle"
9 | minSdkVersion 19
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled true
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:23.1.1'
26 | compile 'com.android.support:design:23.1.1'
27 | compile 'com.jakewharton:butterknife:7.0.1'
28 | compile 'com.squareup.okhttp:okhttp:2.4.0'
29 | compile 'com.squareup.okio:okio:1.4.0'
30 | //bmob-sdk :Bmob的android sdk包
31 | compile 'cn.bmob.android:bmob-sdk:3.4.5'
32 |
33 | compile 'com.google.android.gms:play-services-appindexing:8.1.0'
34 |
35 | compile 'org.greenrobot:eventbus:3.0.0'
36 |
37 | debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2'
38 | releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
39 | testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/utils/SecurityUtils.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.utils;
2 |
3 | /**
4 | * Created by lenovo on 2016/3/26.
5 | */
6 | public class SecurityUtils {
7 |
8 | public static String MD5_secure(String toSecure){
9 | String s = null;
10 | char hexDigits[] = { // 用来将字节转换成 16 进制表示的字符
11 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
12 | try {
13 | java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
14 | md.update(toSecure.getBytes());
15 | byte tmp[] = md.digest(); // MD5 的计算结果是一个 128 位的长整数,
16 | // 用字节表示就是 16 个字节
17 | char str[] = new char[16 * 2]; // 每个字节用 16 进制表示的话,使用两个字符,
18 | // 所以表示成 16 进制需要 32 个字符
19 | int k = 0; // 表示转换结果中对应的字符位置
20 | for (int i = 0; i < 16; i++) { // 从第一个字节开始,对 MD5 的每一个字节
21 | // 转换成 16 进制字符的转换
22 | byte byte0 = tmp[i]; // 取第 i 个字节
23 | str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换,
24 | // >>> 为逻辑右移,将符号位一起右移
25 | str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
26 | }
27 | s = new String(str); // 换后的结果转换为字符串
28 |
29 | } catch (Exception e) {
30 | e.printStackTrace();
31 | }
32 | return s;
33 | }
34 |
35 |
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/imagesplit/Uri2FilePath.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.imagesplit;
2 |
3 | import android.app.Activity;
4 | import android.database.Cursor;
5 | import android.net.Uri;
6 | import android.provider.DocumentsContract;
7 | import android.provider.MediaStore;
8 |
9 | public class Uri2FilePath {
10 | public String path=null;
11 | public Uri2FilePath(Uri uri, Activity activity) {
12 |
13 | String path = "";
14 |
15 | if (DocumentsContract.isDocumentUri(activity, uri)) {
16 |
17 | String wholeID = DocumentsContract.getDocumentId(uri);
18 |
19 | String id = wholeID.split(":")[1];
20 |
21 | String[] column = { MediaStore.Images.Media.DATA };
22 |
23 | String sel = MediaStore.Images.Media._ID + "=?";
24 |
25 | Cursor cursor = activity.getContentResolver().query(
26 |
27 | MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel,
28 |
29 | new String[] { id }, null);
30 |
31 | int columnIndex = cursor.getColumnIndex(column[0]);
32 |
33 | if (cursor.moveToFirst()) {
34 |
35 | path = cursor.getString(columnIndex);
36 |
37 | }
38 |
39 | cursor.close();
40 |
41 | } else {
42 |
43 | String[] projection = { MediaStore.Images.Media.DATA };
44 |
45 | Cursor cursor = activity.getContentResolver().query(uri,
46 |
47 | projection, null, null, null);
48 |
49 | int column_index = cursor
50 |
51 | .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
52 |
53 | cursor.moveToFirst();
54 |
55 | path = cursor.getString(column_index);
56 |
57 | }
58 |
59 |
60 |
61 | this.path=path;
62 |
63 |
64 |
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/PuzzleApplication.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import android.content.SharedPreferences;
6 |
7 | import com.squareup.leakcanary.LeakCanary;
8 |
9 | import cn.bmob.v3.Bmob;
10 | import studio.androiddev.puzzle.dish.DishManager;
11 | import studio.androiddev.puzzle.model.User;
12 | import studio.androiddev.puzzle.utils.StaticValue;
13 |
14 | /**
15 | * Puzzle
16 | * Created by ZQ on 2016/3/21.
17 | */
18 | public class PuzzleApplication extends Application{
19 |
20 | private static Context mContext;
21 |
22 | private static User mUser;
23 |
24 | private static DishManager dm;
25 |
26 | public static int getLevel() {
27 | return level;
28 | }
29 |
30 | public static void setLevel(int level) {
31 | if(level < 3) return;
32 | PuzzleApplication.level = level;
33 | initDishManager();
34 | }
35 |
36 | private static int level = 4;
37 |
38 | @Override
39 | public void onCreate(){
40 | super.onCreate();
41 | LeakCanary.install(this);
42 | Bmob.initialize(this, StaticValue.bmobId);
43 | if(mContext == null) mContext = getApplicationContext();
44 | SharedPreferences pref = getSharedPreferences(StaticValue.SP_NAME, MODE_PRIVATE);
45 | setLevel(pref.getInt(StaticValue.SP_LEVEL, 4));
46 | }
47 |
48 | public static User getmUser() {
49 | return mUser;
50 | }
51 |
52 | public static void setmUser(User mUser) {
53 | PuzzleApplication.mUser = mUser;
54 | }
55 |
56 | public static Context getAppContext(){
57 | return mContext;
58 | }
59 |
60 | public static void initDishManager(){
61 | dm = new DishManager(level);
62 | }
63 |
64 | public static DishManager getDishManager(){
65 | return dm;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/adapter/ChoosePicGridViewAdapter.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.adapter;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ArrayAdapter;
8 | import android.widget.ImageView;
9 |
10 | import studio.androiddev.puzzle.R;
11 | import studio.androiddev.puzzle.activity.ChoosePicActivity;
12 | import studio.androiddev.puzzle.utils.BitmapUtils;
13 |
14 | /**
15 | * puzzle
16 | * Created by ZQ on 2016/4/24.
17 | */
18 | public class ChoosePicGridViewAdapter extends ArrayAdapter {
19 |
20 | int resourceId;
21 |
22 | public ChoosePicGridViewAdapter(Context context, int resourceId){
23 | super(context, resourceId);
24 | this.resourceId = resourceId;
25 | }
26 |
27 | @Override
28 | public int getCount(){
29 | return ChoosePicActivity.icons.length;
30 | }
31 |
32 | @Override
33 | public View getView(int position, View convertView, ViewGroup parent){
34 | ViewHolder holder = null;
35 | View view;
36 | if(convertView == null){
37 | view = LayoutInflater.from(getContext()).inflate(resourceId, null);
38 | holder = new ViewHolder();
39 | holder.imageView = (ImageView) view.findViewById(R.id.imageItem);
40 | view.setTag(holder);
41 | }else{
42 | view = convertView;
43 | holder = (ViewHolder) view.getTag();
44 | }
45 |
46 | holder.imageView.setImageBitmap(BitmapUtils.decodeSampledBitmapFromResources(
47 | getContext().getResources(),
48 | ChoosePicActivity.icons[position],
49 | 300,
50 | 300
51 | ));
52 |
53 | return view;
54 | }
55 |
56 | class ViewHolder{
57 | ImageView imageView;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_game.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
25 |
26 |
27 |
32 |
33 |
34 |
39 |
40 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/model/Record.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.model;
2 |
3 | import java.io.Serializable;
4 | import cn.bmob.v3.BmobObject;
5 |
6 | /**
7 | * Created by lenovo on 2016/3/31.
8 | */
9 |
10 | public class Record extends BmobObject implements Serializable {
11 | String type;
12 | String time;
13 | String phoneNum;
14 | String update_time;
15 | String pic_url;
16 | String nickname;
17 |
18 | public String getType() {
19 | return type;
20 | }
21 |
22 | public void setType(String type) {
23 | this.type = type;
24 | }
25 |
26 | public String getTime() {
27 | return time;
28 | }
29 |
30 | public void setTime(String time) {
31 | this.time = time;
32 | }
33 |
34 | public String getPhoneNum() {
35 | return phoneNum;
36 | }
37 |
38 | public void setPhoneNum(String phoneNum) {
39 | this.phoneNum = phoneNum;
40 | }
41 |
42 | public String getUpdate_time() {
43 | return update_time;
44 | }
45 |
46 | public void setUpdate_time(String update_time) {
47 | this.update_time = update_time;
48 | }
49 |
50 | public String getPic_url() {
51 | return pic_url;
52 | }
53 |
54 | public void setPic_url(String pic_url) {
55 | this.pic_url = pic_url;
56 | }
57 |
58 | public String getNickname() {
59 | return nickname;
60 | }
61 |
62 | public void setNickname(String nickname) {
63 | this.nickname = nickname;
64 | }
65 |
66 | @Override
67 | public String toString() {
68 | return "Record{" +
69 | "type='" + type + '\'' +
70 | ", time='" + time + '\'' +
71 | ", phoneNum='" + phoneNum + '\'' +
72 | ", update_time='" + update_time + '\'' +
73 | ", pic_url='" + pic_url + '\'' +
74 | ", nickname='" + nickname + '\'' +
75 | '}';
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/utils/GameTimer.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.utils;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | import java.util.Timer;
7 | import java.util.TimerTask;
8 |
9 | /**
10 | * puzzle
11 | * Created by ZQ on 2016/4/24.
12 | */
13 | public class GameTimer {
14 | public final static int MESSAGE_TIMER = 0x100;
15 | private static final int INTERVAL_TIME = 1000;
16 | private Handler[] mHandler;
17 | private Timer mTimer;
18 | private TimerTask mTimerTask;
19 |
20 | private int what;
21 | private boolean mTimerStart = false;
22 |
23 | public void recycle(){
24 | stopTimer();
25 | mTimer = null;
26 | mTimerTask = null;
27 | for(Handler handler : mHandler){
28 | handler = null;
29 | }
30 | mHandler = null;
31 | }
32 |
33 | public GameTimer(Handler... handler){
34 | this.mHandler = handler;
35 | this.what = MESSAGE_TIMER;
36 |
37 | mTimer = new Timer();
38 | }
39 |
40 | public void startTimer(){
41 | if(mHandler == null || mTimerStart){
42 | return;
43 | }
44 | mTimerTask = new MyTimerTask();
45 | mTimer.schedule(mTimerTask, INTERVAL_TIME, INTERVAL_TIME);
46 | mTimerStart = true;
47 | }
48 |
49 | public void stopTimer(){
50 | if(!mTimerStart){
51 | return;
52 | }
53 | mTimerStart = false;
54 | if(mTimerTask != null){
55 | mTimerTask.cancel();
56 | mTimerTask = null;
57 | }
58 | mTimer.cancel();
59 |
60 | }
61 |
62 | class MyTimerTask extends TimerTask{
63 | @Override
64 | public void run(){
65 | if(mHandler != null){
66 | for(Handler handler : mHandler){
67 | Message msg = handler.obtainMessage(what);
68 | msg.sendToTarget();
69 | }
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/model/User.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.model;
2 |
3 | import java.io.Serializable;
4 | import cn.bmob.v3.BmobObject;
5 | import cn.bmob.v3.datatype.BmobDate;
6 |
7 | /**
8 | * Created by lenovo on 2016/3/22.
9 | */
10 | public class User extends BmobObject implements Serializable{
11 |
12 | // Integer user_id;
13 | String phoneNum;
14 | String pwd;
15 | String nickName;
16 | BmobDate createTime;
17 | String imgUrl;
18 | String mailNum;
19 |
20 | public String getPhoneNum() {
21 | return phoneNum;
22 | }
23 |
24 | public void setPhoneNum(String phoneNum) {
25 | this.phoneNum = phoneNum;
26 | }
27 |
28 | public String getPwd() {
29 | return pwd;
30 | }
31 |
32 | public void setPwd(String pwd) {
33 | this.pwd = pwd;
34 | }
35 |
36 | public String getNickName() {
37 | return nickName;
38 | }
39 |
40 | public void setNickName(String nickName) {
41 | this.nickName = nickName;
42 | }
43 |
44 | public BmobDate getCreateTime() {
45 | return createTime;
46 | }
47 |
48 | public void setCreateTime(BmobDate createTime) {
49 | this.createTime = createTime;
50 | }
51 |
52 | public String getImgUrl() {
53 | return imgUrl;
54 | }
55 |
56 | public void setImgUrl(String imgUrl) {
57 | this.imgUrl = imgUrl;
58 | }
59 |
60 | public String getMailNum() {
61 | return mailNum;
62 | }
63 |
64 | public void setMailNum(String mailNum) {
65 | this.mailNum = mailNum;
66 | }
67 |
68 | @Override
69 | public String toString() {
70 | return "User{" +
71 | "phoneNum='" + phoneNum + '\'' +
72 | ", pwd='" + pwd + '\'' +
73 | ", nickName='" + nickName + '\'' +
74 | ", createTime=" + createTime +
75 | ", imgUrl='" + imgUrl + '\'' +
76 | ", mailNum='" + mailNum + '\'' +
77 | '}';
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/activity/ChoosePicActivity.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.activity;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.widget.Toolbar;
7 | import android.view.MenuItem;
8 | import android.view.View;
9 | import android.widget.AdapterView;
10 | import android.widget.GridView;
11 |
12 | import butterknife.Bind;
13 | import butterknife.ButterKnife;
14 | import studio.androiddev.puzzle.R;
15 | import studio.androiddev.puzzle.adapter.ChoosePicGridViewAdapter;
16 |
17 | public class ChoosePicActivity extends BaseActivity {
18 |
19 | @Bind(R.id.toolbar)
20 | Toolbar toolbar;
21 | @Bind(R.id.picContainer)
22 | GridView picContainer;
23 |
24 | public static final int [] icons={
25 | R.drawable.default1,
26 | R.drawable.default2,
27 | R.drawable.default3,
28 | R.drawable.default4,
29 | R.drawable.default5,
30 | R.drawable.default6
31 | };
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | setContentView(R.layout.activity_choose_pic);
37 | ButterKnife.bind(this);
38 | setSupportActionBar(toolbar);
39 | initView();
40 |
41 | }
42 |
43 | private void initView() {
44 |
45 | toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);
46 |
47 | picContainer.setAdapter(new ChoosePicGridViewAdapter(ChoosePicActivity.this, R.layout.choose_pic_gridview_item));
48 | picContainer.setOnItemClickListener(new AdapterView.OnItemClickListener() {
49 | @Override
50 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
51 |
52 | GameActivity.actionStart(ChoosePicActivity.this, position);
53 |
54 | }
55 | });
56 | }
57 |
58 | @Override
59 | public boolean onOptionsItemSelected(MenuItem item) {
60 | if (item.getItemId() == android.R.id.home) {
61 | finish();
62 | return true;
63 | }
64 | return super.onOptionsItemSelected(item);
65 | }
66 |
67 | public static void actionStart(Context context) {
68 | Intent intent = new Intent(context, ChoosePicActivity.class);
69 | context.startActivity(intent);
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_register.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
18 |
28 |
29 |
39 |
40 |
50 |
51 |
52 |
61 |
62 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
23 |
24 |
33 |
34 |
43 |
44 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_game.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
18 |
24 |
29 |
30 |
39 |
40 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/bgm/MusicServer.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.bgm;
2 |
3 | /**
4 | * Created by Administrator on 2016/3/29.
5 | */
6 |
7 | import android.app.Service;
8 | import android.content.Intent;
9 | import android.media.MediaPlayer;
10 | import android.os.IBinder;
11 |
12 | import java.io.IOException;
13 |
14 | import studio.androiddev.puzzle.R;
15 |
16 | public class MusicServer extends Service {
17 |
18 | private MediaPlayer mediaPlayer;
19 | private int songList[]={R.raw.a, R.raw.b, R.raw.c,R.raw.d};
20 | private int songIndex = 0;
21 | @Override
22 | public IBinder onBind(Intent intent) {
23 |
24 | return null;
25 | }
26 |
27 | @Override
28 | public void onCreate() {
29 | super.onCreate();
30 | }
31 | @Override
32 | public int onStartCommand(Intent intent, int flags, int startId){
33 |
34 | if(mediaPlayer==null){
35 | // R.raw.mmp是资源文件,MP3格式的
36 | try {
37 | nextsong();
38 | mediaPlayer.setOnCompletionListener(new CompletionListener());
39 | } catch (IOException e) {
40 | e.printStackTrace();
41 | }
42 |
43 | }
44 |
45 | return super.onStartCommand(intent, flags, startId);
46 | }
47 |
48 | private final class CompletionListener implements MediaPlayer.OnCompletionListener {
49 |
50 | @Override
51 | public void onCompletion(MediaPlayer mp) {
52 | try {
53 | nextsong();
54 | } catch (IOException e) {
55 | e.printStackTrace();
56 | }
57 | }
58 |
59 | }
60 | public void nextsong() throws IOException {
61 | songIndex = 0 + (int)(Math.random() * 4);
62 | songplay();
63 | }
64 | private void songplay() throws IOException {
65 | try {
66 | if(mediaPlayer!=null)
67 | mediaPlayer.release();
68 | mediaPlayer=MediaPlayer.create(this, songList[songIndex]);
69 | mediaPlayer.start();
70 | } catch (IllegalArgumentException e) {
71 | e.printStackTrace();
72 | } catch (SecurityException e) {
73 | e.printStackTrace();
74 | } catch (IllegalStateException e) {
75 | e.printStackTrace();
76 | }
77 |
78 | }
79 |
80 |
81 | @Override
82 | public void onDestroy() {
83 | super.onDestroy();
84 | mediaPlayer.stop();
85 | mediaPlayer = null;
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
17 |
18 |
19 |
29 |
30 |
40 |
41 |
50 |
51 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 拼了个图
2 | 
3 |
4 | ## 简介
5 | **拼了个图**是一款Android平台上的拼图小游戏。
6 | This repo is an awesome puzzle game on Android platform.
7 | 编译源码前,请先[下载](http://7vzrj0.com1.z0.glb.clouddn.com/puzzlebgm.rar)背景音乐文件,解压放到*/app/src/main/res/raw/*目录下。
8 | Before you build this repo, you should download [bgm](http://7vzrj0.com1.z0.glb.clouddn.com/puzzlebgm.rar) file and unzip it into */app/src/main/res/raw/* directory.
9 | ## 界面截图
10 | #### 登录页
11 | 
12 | #### 主界面
13 | 
14 | #### 关卡选择
15 | 
16 | #### 游戏界面
17 | 
18 | #### 游戏胜利
19 | 
20 | #### 发现(最新的游戏记录)
21 | 
22 | #### 设置和分享
23 | 
24 | 
25 | #### 个人中心
26 | 
27 |
28 | ## 设计图
29 | 
30 |
31 | ## 协议
32 | The MIT License (MIT)
33 |
34 | Copyright (c) 2016 FreedomZZQ & haze & YouJoin Studio
35 |
36 | Permission is hereby granted, free of charge, to any person obtaining a copy
37 | of this software and associated documentation files (the "Software"), to deal
38 | in the Software without restriction, including without limitation the rights
39 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40 | copies of the Software, and to permit persons to whom the Software is
41 | furnished to do so, subject to the following conditions:
42 |
43 | The above copyright notice and this permission notice shall be included in all
44 | copies or substantial portions of the Software.
45 |
46 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
51 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
52 | SOFTWARE.
53 |
54 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_lv_rank.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
28 |
29 |
30 |
37 |
38 |
48 |
49 |
58 |
59 |
60 |
61 |
62 |
73 |
74 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_change_pwd.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
20 |
21 |
33 |
34 |
46 |
47 |
59 |
60 |
61 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
25 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
37 |
41 |
44 |
48 |
52 |
56 |
57 |
58 |
59 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.activity;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.widget.Toolbar;
7 | import android.view.KeyEvent;
8 | import android.view.View;
9 | import android.widget.ImageButton;
10 | import android.widget.Toast;
11 |
12 | import butterknife.Bind;
13 | import butterknife.ButterKnife;
14 | import butterknife.OnClick;
15 | import studio.androiddev.puzzle.PuzzleApplication;
16 | import studio.androiddev.puzzle.R;
17 |
18 | public class MainActivity extends BaseActivity {
19 |
20 | @Bind(R.id.beginButton)
21 | ImageButton beginButton;
22 | @Bind(R.id.rankButton)
23 | ImageButton rankButton;
24 | @Bind(R.id.settingButton)
25 | ImageButton settingButton;
26 | @Bind(R.id.exitButton)
27 | ImageButton exitButton;
28 | @Bind(R.id.toolbar)
29 | Toolbar toolbar;
30 | @Bind(R.id.userButton)
31 | ImageButton userButton;
32 |
33 | //用于记录两次按下返回键的间隔
34 | private long exitTime = 0;
35 |
36 | @Override
37 | protected void onCreate(Bundle savedInstanceState) {
38 | super.onCreate(savedInstanceState);
39 | setContentView(R.layout.activity_main);
40 | ButterKnife.bind(this);
41 | toolbar.setTitle("");
42 | setSupportActionBar(toolbar);
43 | // PuzzleApplication.initDishManager(4);
44 |
45 | }
46 |
47 | @Override
48 | protected void onDestroy(){
49 | super.onDestroy();
50 | }
51 |
52 | @OnClick({R.id.beginButton, R.id.rankButton, R.id.settingButton, R.id.exitButton})
53 | public void onClick(View view) {
54 | switch (view.getId()) {
55 | case R.id.beginButton:
56 | ChoosePicActivity.actionStart(MainActivity.this);
57 | break;
58 | case R.id.rankButton:
59 | RankActivity.actionStart(MainActivity.this);
60 | break;
61 | case R.id.settingButton:
62 | SettingActivity.actionStart(MainActivity.this);
63 | break;
64 | case R.id.exitButton:
65 | ActivityManager.finishAll();
66 | break;
67 | }
68 | }
69 |
70 |
71 |
72 | @Override
73 | public boolean onKeyDown(int keyCode, KeyEvent event) {
74 | if (keyCode == KeyEvent.KEYCODE_BACK) {
75 | //在两秒内两次按下返回键退出程序
76 | if ((System.currentTimeMillis() - exitTime) > 2000) {
77 | Toast.makeText(MainActivity.this, getString(R.string.click_again_to_exit), Toast.LENGTH_SHORT).show();
78 | exitTime = System.currentTimeMillis();
79 | } else {
80 | ActivityManager.finishAll();
81 | }
82 | return true;
83 | }
84 | return super.onKeyDown(keyCode, event);
85 | }
86 |
87 | public static void actionStart(Context context) {
88 | Intent intent = new Intent(context, MainActivity.class);
89 | context.startActivity(intent);
90 | }
91 |
92 | @OnClick(R.id.userButton)
93 | public void onClick() {
94 | UserInfoActivity.actionStart(MainActivity.this);
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/activity/RegisterActivity.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.activity;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.widget.EditText;
6 | import android.widget.ImageButton;
7 | import android.widget.Toast;
8 |
9 | import java.util.Date;
10 |
11 | import butterknife.Bind;
12 | import butterknife.ButterKnife;
13 | import butterknife.OnClick;
14 | import cn.bmob.v3.datatype.BmobDate;
15 | import cn.bmob.v3.listener.SaveListener;
16 | import studio.androiddev.puzzle.R;
17 | import studio.androiddev.puzzle.model.User;
18 | import studio.androiddev.puzzle.utils.RegExUtil;
19 | import studio.androiddev.puzzle.utils.SecurityUtils;
20 |
21 | public class RegisterActivity extends BaseActivity {
22 |
23 |
24 | @Bind(R.id.et_phone_reg)
25 | EditText etPhoneReg;
26 | @Bind(R.id.et_pwd_register)
27 | EditText etPwdRegister;
28 | @Bind(R.id.et_pwd_confirm_register)
29 | EditText etPwdConfirmRegister;
30 | @Bind(R.id.btn_register_res)
31 | ImageButton btnRegisterRes;
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | setContentView(R.layout.activity_register);
37 | ButterKnife.bind(this);
38 |
39 | }
40 |
41 | private void regSaveInLocal(User user) {
42 |
43 | }
44 |
45 | private void regPushToBmob(User user) {
46 |
47 | user.save(this, new SaveListener() {
48 | @Override
49 | public void onSuccess() {
50 | Toast.makeText(RegisterActivity.this, "注册成功", Toast.LENGTH_LONG).show();
51 | Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
52 | startActivity(intent);
53 | }
54 |
55 | @Override
56 | public void onFailure(int i, String s) {
57 | Toast.makeText(RegisterActivity.this, "数据存储失败,请检查网络", Toast.LENGTH_LONG).show();
58 | }
59 | });
60 | }
61 |
62 |
63 | @OnClick(R.id.btn_register_res)
64 | public void onClick() {
65 | if (RegExUtil.confirmPhone(etPhoneReg.getText().toString())) {
66 | if (RegExUtil.confirmPwd(etPwdRegister.getText().toString())) {
67 | if (etPwdRegister.getText().toString().equals(etPwdConfirmRegister.getText().toString())) {
68 |
69 | User temp = new User();
70 | temp.setPhoneNum(etPhoneReg.getText().toString());
71 | String pwd_MD5 = SecurityUtils.MD5_secure(etPwdRegister.getText().toString());
72 | temp.setPwd(pwd_MD5);
73 | temp.setCreateTime(new BmobDate(new Date()));
74 | temp.setImgUrl("null");
75 | temp.setMailNum("待添加");
76 | temp.setNickName("待添加");
77 | regPushToBmob(temp);
78 | regSaveInLocal(temp);
79 |
80 | } else {
81 | etPwdConfirmRegister.setError("两次密码输入不一致!");
82 | }
83 |
84 | } else {
85 | etPwdRegister.setError("密码至少为8位数字或字符");
86 | }
87 |
88 | } else {
89 | etPhoneReg.setError("手机号码格式错误");
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/activity/ChangePwdActivity.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.activity;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.widget.Toolbar;
7 | import android.util.Log;
8 | import android.view.MenuItem;
9 | import android.widget.Button;
10 | import android.widget.EditText;
11 | import android.widget.Toast;
12 |
13 | import butterknife.Bind;
14 | import butterknife.ButterKnife;
15 | import butterknife.OnClick;
16 | import cn.bmob.v3.listener.UpdateListener;
17 | import studio.androiddev.puzzle.PuzzleApplication;
18 | import studio.androiddev.puzzle.R;
19 | import studio.androiddev.puzzle.model.User;
20 | import studio.androiddev.puzzle.utils.SecurityUtils;
21 |
22 | public class ChangePwdActivity extends BaseActivity {
23 | @Bind(R.id.et_pwd_old)
24 | EditText met_oldPwd;
25 | @Bind(R.id.et_pwd_new)
26 | EditText met_newPwd;
27 | @Bind(R.id.et_confirm_new_pwd)
28 | EditText met_confirmPwd;
29 | @Bind(R.id.btn_changePwd_confirm)
30 | Button mbtn_confirmChangePwd;
31 | @Bind(R.id.toolbar)
32 | Toolbar toolbar;
33 |
34 | @Override
35 | protected void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | setContentView(R.layout.activity_change_pwd);
38 | ButterKnife.bind(this);
39 | setSupportActionBar(toolbar);
40 | toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);
41 |
42 | }
43 |
44 | @Override
45 | public boolean onOptionsItemSelected(MenuItem item) {
46 |
47 | if (item.getItemId() == android.R.id.home) {
48 | finish();
49 | return true;
50 | }
51 |
52 | return super.onOptionsItemSelected(item);
53 | }
54 |
55 | @OnClick(R.id.btn_changePwd_confirm)
56 | public void onClick() {
57 | String oldPwd = SecurityUtils.MD5_secure(met_oldPwd.getText().toString());
58 | String newPwd = met_newPwd.getText().toString();
59 | String newConPwd = met_confirmPwd.getText().toString();
60 | User mUser = PuzzleApplication.getmUser();
61 | if (mUser.getPwd().equals(oldPwd)) {
62 | if (newPwd.equals(newConPwd)) {
63 | String s = SecurityUtils.MD5_secure(newPwd);
64 | mUser.setPwd(s);
65 | mUser.update(ChangePwdActivity.this, mUser.getObjectId(), new UpdateListener() {
66 | @Override
67 | public void onSuccess() {
68 | Toast.makeText(ChangePwdActivity.this, "修改密码成功", Toast.LENGTH_SHORT).show();
69 | Intent intent = new Intent();
70 | setResult(333, intent);
71 | finish();
72 | }
73 |
74 | @Override
75 | public void onFailure(int i, String s) {
76 | Log.e("main", s);
77 | }
78 | });
79 | } else {
80 | met_confirmPwd.setError("密码输入不一致");
81 | }
82 | } else {
83 | Toast.makeText(ChangePwdActivity.this, "原密码输入错误,请重新输入!", Toast.LENGTH_SHORT).show();
84 | }
85 | }
86 |
87 | public static void actionStart(Activity context) {
88 | Intent intent = new Intent(context, ChangePwdActivity.class);
89 | context.startActivityForResult(intent, 1234);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/activity/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.activity;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.util.Log;
7 | import android.view.View;
8 | import android.widget.EditText;
9 | import android.widget.ImageButton;
10 | import android.widget.Toast;
11 |
12 | import java.util.List;
13 |
14 | import butterknife.Bind;
15 | import butterknife.ButterKnife;
16 | import butterknife.OnClick;
17 | import cn.bmob.v3.BmobQuery;
18 | import cn.bmob.v3.listener.FindListener;
19 | import studio.androiddev.puzzle.PuzzleApplication;
20 | import studio.androiddev.puzzle.R;
21 | import studio.androiddev.puzzle.model.User;
22 | import studio.androiddev.puzzle.utils.RegExUtil;
23 | import studio.androiddev.puzzle.utils.SecurityUtils;
24 |
25 | public class LoginActivity extends BaseActivity {
26 | @Bind(R.id.et_phone)
27 | EditText met_phone;
28 | @Bind(R.id.et_pwd)
29 | EditText met_pwd;
30 | @Bind(R.id.btn_register)
31 | ImageButton mbtn_register;
32 | @Bind(R.id.btn_login)
33 | ImageButton mbtn_login;
34 |
35 | @Override
36 | protected void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | // Bmob.initialize(this, StaticValue.bmobId);
39 | setContentView(R.layout.activity_login);
40 | ButterKnife.bind(this);
41 |
42 | }
43 |
44 | @OnClick({R.id.btn_register, R.id.btn_login})
45 | public void onClick(View view) {
46 | switch (view.getId()) {
47 | case R.id.btn_register:
48 | //注册按钮点击事件
49 | Intent intent = new Intent(LoginActivity.this, RegisterActivity.class);
50 | startActivity(intent);
51 | break;
52 | case R.id.btn_login:
53 | //登录按钮点击事件
54 | final String phone = met_phone.getText().toString();
55 | final String pwd = met_pwd.getText().toString();
56 |
57 | if (RegExUtil.confirmPhone(phone)) {
58 | if (RegExUtil.confirmPwd(pwd)) {
59 |
60 | // 登录验证逻辑函数
61 | BmobQuery query = new BmobQuery();
62 | query.addWhereEqualTo("phoneNum", phone);
63 | query.findObjects(PuzzleApplication.getAppContext(), new FindListener() {
64 | @Override
65 | public void onSuccess(List list) {
66 | if (list.size() == 1) {
67 | String pwd_MD5_Bmob = list.get(0).getPwd();
68 | String pwd_MD5_Local = SecurityUtils.MD5_secure(pwd);
69 | if (pwd_MD5_Bmob.equals(pwd_MD5_Local)) {
70 | //登陆成功后要做三件事:
71 | //1.更新Application中的User
72 | //2.启动MainActivity
73 | //3.清空输入框
74 | PuzzleApplication.setmUser(list.get(0));
75 | MainActivity.actionStart(LoginActivity.this);
76 | met_phone.setText("");
77 | met_pwd.setText("");
78 | } else {
79 | Toast.makeText(LoginActivity.this, "输入密码错误,请重新输入!", Toast.LENGTH_SHORT).show();
80 | }
81 | } else if (list.size() == 0) {
82 | Toast.makeText(LoginActivity.this, "不存在该账号,请注册!", Toast.LENGTH_SHORT).show();
83 | }
84 | }
85 |
86 | @Override
87 | public void onError(int i, String s) {
88 | Log.e("main", s);
89 | }
90 | });
91 |
92 | } else {
93 | met_pwd.setError("密码格式错误,请重新输入!");
94 | }
95 |
96 | } else {
97 | met_phone.setError("手机号格式错误,请重新输入!");
98 | }
99 | break;
100 | }
101 | }
102 |
103 | public static void actionStart(Context context){
104 | Intent intent = new Intent(context, LoginActivity.class);
105 | context.startActivity(intent);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/activity/SettingActivity.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.activity;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.Intent;
7 | import android.content.SharedPreferences;
8 | import android.os.Bundle;
9 | import android.support.v7.widget.Toolbar;
10 | import android.view.MenuItem;
11 | import android.view.View;
12 | import android.widget.Button;
13 | import android.widget.ImageButton;
14 |
15 | import butterknife.Bind;
16 | import butterknife.ButterKnife;
17 | import butterknife.OnClick;
18 | import studio.androiddev.puzzle.PuzzleApplication;
19 | import studio.androiddev.puzzle.R;
20 | import studio.androiddev.puzzle.utils.StaticValue;
21 |
22 | public class SettingActivity extends BaseActivity {
23 |
24 | @Bind(R.id.toolbar)
25 | Toolbar toolbar;
26 | @Bind(R.id.levelChooseButton)
27 | Button levelChooseButton;
28 | @Bind(R.id.buttonShare)
29 | ImageButton buttonShare;
30 |
31 | private int choosedLevel = 0;
32 |
33 | final int[] levels = {
34 | R.string.setting_level_3,
35 | R.string.setting_level_4,
36 | R.string.setting_level_5,
37 | R.string.setting_level_6};
38 |
39 | @Override
40 | protected void onCreate(Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 | setContentView(R.layout.activity_setting);
43 | ButterKnife.bind(this);
44 | setSupportActionBar(toolbar);
45 |
46 | toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);
47 | levelChooseButton.setText(getString(levels[PuzzleApplication.getLevel() - 3]));
48 |
49 | }
50 |
51 | @Override
52 | public boolean onOptionsItemSelected(MenuItem item) {
53 | if (item.getItemId() == android.R.id.home) {
54 | finish();
55 | return true;
56 | }
57 | return super.onOptionsItemSelected(item);
58 | }
59 |
60 | public static void actionStart(Context context) {
61 | Intent intent = new Intent(context, SettingActivity.class);
62 | context.startActivity(intent);
63 | }
64 |
65 | private void chooseLevel() {
66 | final AlertDialog.Builder builder = new AlertDialog.Builder(SettingActivity.this);
67 |
68 | final String[] levels = {
69 | getString(R.string.setting_level_3),
70 | getString(R.string.setting_level_4),
71 | getString(R.string.setting_level_5),
72 | getString(R.string.setting_level_6)};
73 |
74 | builder.setTitle("请选择难度");
75 | int defaultWhich = 0;
76 |
77 | for (int i = 0; i < levels.length; i++) {
78 | if (levelChooseButton.getText().toString().equals(levels[i])) {
79 | defaultWhich = i;
80 | }
81 | }
82 |
83 | builder.setSingleChoiceItems(levels, defaultWhich,
84 | new DialogInterface.OnClickListener() {
85 | @Override
86 | public void onClick(DialogInterface dialog, int which) {
87 | choosedLevel = which;
88 | }
89 | });
90 | builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
91 | @Override
92 | public void onClick(DialogInterface dialog, int which) {
93 | levelChooseButton.setText(levels[choosedLevel]);
94 | changeLevel();
95 | }
96 | });
97 | builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
98 | @Override
99 | public void onClick(DialogInterface dialog, int which) {
100 |
101 | }
102 | });
103 | builder.show();
104 | }
105 |
106 | private void changeLevel() {
107 |
108 | int level = choosedLevel + 3;
109 | SharedPreferences.Editor editor = getSharedPreferences(StaticValue.SP_NAME, MODE_PRIVATE).edit();
110 | editor.putInt(StaticValue.SP_LEVEL, level);
111 | editor.apply();
112 | PuzzleApplication.setLevel(level);
113 | }
114 |
115 | private void shareAction(){
116 | Intent shareIntent = new Intent();
117 | shareIntent.setAction(Intent.ACTION_SEND);
118 | shareIntent.putExtra(Intent.EXTRA_TEXT, getResources().getString(R.string.setting_share));
119 | shareIntent.setType("text/plain");
120 |
121 | //设置分享列表的标题,并且每次都显示分享列表
122 | startActivity(Intent.createChooser(shareIntent, "分享到"));
123 | }
124 |
125 | @OnClick({R.id.levelChooseButton, R.id.buttonShare})
126 | public void onClick(View view) {
127 | switch (view.getId()) {
128 | case R.id.levelChooseButton:
129 | chooseLevel();
130 | break;
131 | case R.id.buttonShare:
132 | shareAction();
133 | break;
134 | }
135 | }
136 |
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\ZQ\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # --------------------------General----------------------------
20 | -optimizationpasses 5
21 | -dontusemixedcaseclassnames
22 | -dontskipnonpubliclibraryclasses
23 | # -dontskipnonpubliclibraryclassmembers
24 | -dontpreverify
25 | -verbose
26 | -printmapping proguardMapping.txt
27 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
28 | -keepattributes *Annotation*
29 | -keepattributes Signature
30 | -keepattributes SourceFile,LineNumberTable
31 | -keepclasseswithmembernames class * {
32 | native ;
33 | }
34 | -keep public class * extends android.app.Activity
35 | -keep public class * extends android.app.Application
36 | -keep public class * extends android.app.Service
37 | -keep public class * extends android.content.BroadcastReceiver
38 | -keep public class * extends android.content.ContentProvider
39 | -keep public class * extends android.app.backup.BackupAgentHelper
40 | -keep public class * extends android.preference.Preference
41 | -keep public class * extends android.view.View
42 | -keep public class com.android.vending.licensing.ILicensingService
43 | -keep public class com.tuniu.app.ui.fragment.** {*;}
44 |
45 | -keepclassmembers class * extends android.app.Activity{
46 | public void *(android.view.View);
47 | }
48 |
49 | -keepclassmembers enum * {
50 | public static **[] values();
51 | public static ** valueOf(java.lang.String);
52 | }
53 |
54 | -keep public class * extends android.view.View {
55 | *** get*();
56 | void set*(***);
57 | public (android.content.Context);
58 | public (android.content.Context, android.util.AttributeSet);
59 | public (android.content.Context, android.util.AttributeSet, int);
60 | }
61 |
62 | -keep class * implements android.os.Parcelable {
63 | public static final android.os.Parcelable$Creator *;
64 | }
65 |
66 | -keepclassmembers class * implements java.io.Serializable {
67 | static final long serialVersionUID;
68 | private static final java.io.ObjectStreamField[] serialPersistentFields;
69 | private void writeObject(java.io.ObjectOutputStream);
70 | private void readObject(java.io.ObjectInputStream);
71 | java.lang.Object writeReplace();
72 | java.lang.Object readResolve();
73 | }
74 |
75 | -keep class **.R$* {
76 | *;
77 | }
78 |
79 | -keepclassmembers class * {
80 | void *(**On*Event);
81 | }
82 |
83 | # 不混淆实体类
84 | -keep public class studio.androiddev.puzzle.model.** {
85 | *;
86 | }
87 |
88 | # --------------------------EventBus 3.0----------------------------
89 | -keepattributes *Annotation*
90 | -keepclassmembers class ** {
91 | @org.greenrobot.eventbus.Subscribe ;
92 | }
93 | -keep enum org.greenrobot.eventbus.ThreadMode { *; }
94 |
95 | # Only required if you use AsyncExecutor
96 | -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
97 | (java.lang.Throwable);
98 | }
99 |
100 |
101 | # --------------------------ButterKnife----------------------------
102 | -keep class butterknife.** { *; }
103 | -dontwarn butterknife.internal.**
104 | -keep class **$$ViewBinder { *; }
105 |
106 | -keepnames class * { @butterknife.Bind *;}
107 |
108 | -keepclasseswithmembernames class * {
109 | @butterknife.* ;
110 | }
111 |
112 | -keepclasseswithmembernames class * {
113 | @butterknife.* ;
114 | }
115 |
116 |
117 | # --------------------------Bmob----------------------------
118 | -ignorewarnings
119 |
120 | -keepattributes Signature
121 |
122 | # 不混淆BmobSDK
123 | -keep class cn.bmob.v3.** {*;}
124 |
125 | # 保证继承自BmobObject、BmobUser类的JavaBean不被混淆
126 | -keep class * extends cn.bmob.v3.BmobObject {
127 | *;
128 | }
129 | -keep class studio.androiddev.puzzle.model.Record{*;}
130 | -keep class studio.androiddev.puzzle.model.User{*;}
131 |
132 | # 如果你使用了okhttp、okio的包,请添加以下混淆代码
133 | -dontwarn com.squareup.okhttp.**
134 | -keep class com.squareup.okhttp.** { *;}
135 | -keep interface com.squareup.okhttp.** { *; }
136 | -dontwarn okio.**
137 |
138 | # 如果你需要兼容6.0系统,请不要混淆org.apache.http.legacy.jar
139 | -dontwarn android.net.compatibility.**
140 | -dontwarn android.net.http.**
141 | -dontwarn com.android.internal.http.multipart.**
142 | -dontwarn org.apache.commons.**
143 | -dontwarn org.apache.http.**
144 | -keep class android.net.compatibility.**{*;}
145 | -keep class android.net.http.**{*;}
146 | -keep class com.android.internal.http.multipart.**{*;}
147 | -keep class org.apache.commons.**{*;}
148 | -keep class org.apache.http.**{*;}
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/imagesplit/ImageSplitter.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.imagesplit;
2 |
3 | /**
4 | * Created by Administrator on 2016/3/27.
5 | */
6 |
7 | import android.graphics.Bitmap;
8 | import android.graphics.Canvas;
9 | import android.graphics.Matrix;
10 | import android.graphics.Paint;
11 | import android.graphics.PorterDuff;
12 | import android.graphics.PorterDuffXfermode;
13 | import android.util.Log;
14 |
15 | import java.io.FileNotFoundException;
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | import studio.androiddev.puzzle.dish.DishManager;
20 |
21 | public class ImageSplitter {
22 |
23 | private static final String TAG = "puzzle";
24 |
25 | public static List split(Bitmap bitmap, int level, int dishWidth, int dishHeight)
26 | throws FileNotFoundException {
27 | // Bitmap[] bmcover = DishManager.getBitmapCover();
28 | List pieces = new ArrayList<>(level * level);
29 |
30 | float pieceWidth = (float) dishWidth / level;
31 | float pieceHeight = (float) dishHeight / level;
32 | PorterDuffXfermode pdf = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
33 | Log.d(TAG, "pieceWidth: " + pieceWidth);
34 |
35 | int k;
36 | Log.d(TAG, "circle begin");
37 | for (int i = 0; i < level; i++) {
38 | for (int j = 0; j < level; j++) {
39 | if(i == 0) {
40 | if (j == 0) {
41 | k = DishManager.COVER_TOP_LEFT;
42 | } else if(j == level - 1) {
43 | k = DishManager.COVER_TOP_RIGHT;
44 | }
45 | else {
46 | k = DishManager.COVER_TOP;
47 | }
48 | }
49 | else if(i == level - 1) {
50 | if(j == 0) {
51 | k = DishManager.COVER_BOTTOM_LEFT;
52 | } else if (j == level - 1) {
53 | k = DishManager.COVER_BOTTOM_RIGHT;
54 | } else{
55 | k = DishManager.COVER_BOTTOM;
56 | }
57 | }
58 | else if(j == 0) {
59 | k = DishManager.COVER_LEFT;
60 | }else if(j == level - 1) {
61 | k = DishManager.COVER_RIGHT;
62 | }else {
63 | k = DishManager.COVER_CENTER;
64 | }
65 |
66 | Log.d(TAG, "piece " + k + " compute completed");
67 |
68 | ImagePiece piece = new ImagePiece();
69 | piece.index = j + i * level;
70 | float xValue, yValue;
71 |
72 | if(j != 0) {
73 | //xValue = (int) (j * (pieceWidth - pieceWidth * 0.25));
74 | xValue = (int) (j * pieceWidth - pieceWidth * 0.25);
75 | }
76 | else {
77 | xValue = j * pieceWidth;
78 | }
79 | if(i != 0) {
80 | //yValue = (int) (i * (pieceHeight - pieceWidth * 0.25));
81 | yValue = i * pieceHeight;
82 | if(i != level - 1){
83 | yValue += 0.25f * pieceHeight;
84 | }
85 | }
86 | else {
87 | yValue = i * pieceHeight;
88 | }
89 |
90 | // xValue = j * pieceWidth;
91 | // yValue = i * pieceHeight;
92 |
93 | Bitmap drawingBitmap = Bitmap.createBitmap((int) pieceWidth,
94 | (int) pieceHeight, Bitmap.Config.ARGB_8888);
95 | Canvas canvas = new Canvas(drawingBitmap);
96 | Paint paint = new Paint();
97 |
98 | //final float scale = DensityUtil.getScale(PuzzleApplication.getAppContext());
99 | Bitmap cover = DishManager.getCover(k);
100 | final float scale = pieceWidth / cover.getWidth();
101 | Matrix matrix = new Matrix();
102 | matrix.setScale(scale, scale);
103 | canvas.drawBitmap(cover, matrix, paint);
104 | cover.recycle();
105 | // canvas.drawBitmap(bmcover[k], 0, 0, paint);
106 |
107 | float width = pieceWidth;
108 | float height = pieceHeight;
109 | if(i != level - 1){
110 | height += pieceHeight * 0.25f;
111 | }
112 | if(j != 0){
113 | width += pieceWidth * 0.25f;
114 | }
115 |
116 | paint.setXfermode(pdf);
117 | piece.bitmap = Bitmap.createBitmap(
118 | bitmap,
119 | (int) xValue, (int) yValue,
120 | (int) width, (int) height);
121 |
122 | canvas.drawBitmap(piece.bitmap, 0, 0, paint);
123 | piece.bitmap.recycle();
124 | piece.bitmap = drawingBitmap;
125 | pieces.add(piece);
126 | Log.d(TAG, "piece " + k + " draw completed");
127 | }
128 | }
129 | System.gc();
130 |
131 | return pieces;
132 | }
133 |
134 | }
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/utils/BitmapUtils.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.utils;
2 |
3 | import android.content.res.Resources;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapFactory;
6 | import android.graphics.Matrix;
7 |
8 | import java.io.FileNotFoundException;
9 |
10 | public class BitmapUtils {
11 |
12 | public static Bitmap scaleBitmap(Bitmap bitmap, float scale) {
13 | Matrix matrix = new Matrix();
14 | matrix.postScale(scale, scale);
15 | return Bitmap.createBitmap(bitmap, 0, 0,
16 | bitmap.getWidth(),
17 | bitmap.getHeight(),
18 | matrix, true);
19 | }
20 |
21 | public static Bitmap decodeSampledBitmapFromResources(Resources res, int resId,
22 | int reqWidth, int reqHeight){
23 | final BitmapFactory.Options options = new BitmapFactory.Options();
24 | options.inJustDecodeBounds = true;
25 | BitmapFactory.decodeResource(res, resId, options);
26 |
27 | options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
28 |
29 | options.inJustDecodeBounds = false;
30 | return BitmapFactory.decodeResource(res, resId, options);
31 | }
32 | private static int calculateInSampleSize(BitmapFactory.Options options,
33 | int reqWidth, int reqHeight) {
34 | final int height = options.outHeight;
35 | final int width = options.outWidth;
36 | int inSampleSize = 1;
37 | if (height > reqHeight || width > reqWidth) {
38 | final int halfHeight = height/2 ;
39 | final int halfWidth = width/2 ;
40 | while ((halfHeight / inSampleSize) > reqHeight
41 | && (halfWidth / inSampleSize) > reqWidth) {
42 | inSampleSize *= 2;
43 | }
44 | }
45 | return inSampleSize;
46 | }
47 |
48 |
49 |
50 | public static Bitmap createNoRecycleScaleBitmap(Bitmap src, int dstWidth,
51 | double dstHeight) {
52 | int k=(int) dstHeight;
53 | return Bitmap.createScaledBitmap(src, dstWidth, k, true);
54 | }
55 | //如果是放大图片,filter决定是否平滑,如果是缩小图片,filter无影响
56 | public static Bitmap createScaleBitmap(Bitmap src, int dstWidth,
57 | double dstHeight) {
58 | int k=(int) dstHeight;
59 | Bitmap dst = Bitmap.createScaledBitmap(src, dstWidth, k, true);
60 | if (src != dst) { //如果没有缩放,那么不回收
61 | src.recycle(); // 释放Bitmap的native像素数组
62 | }
63 | return dst;
64 | }
65 |
66 | public static Bitmap createScaleBitmap(Bitmap src, double dstWidth,
67 | int dstHeight) {
68 | int k=(int) dstWidth;
69 | Bitmap dst = Bitmap.createScaledBitmap(src, k,dstHeight, true);
70 | if (src != dst) { //如果没有缩放,那么不回收
71 | src.recycle(); // 释放Bitmap的native像素数组
72 | }
73 | return dst;
74 | }
75 |
76 |
77 | // ��Resources�м���ͼƬ
78 | public Bitmap decodeSampledBitmapFromPath(String url, int reqWidth, int reqHeight,boolean change)
79 | throws FileNotFoundException {
80 | final BitmapFactory.Options options = new BitmapFactory.Options();
81 | options.inJustDecodeBounds = true;
82 |
83 |
84 |
85 | BitmapFactory.decodeFile(url, options);
86 | int size;
87 | /*double re=0;
88 | re= ((double) options.outWidth)/options.outHeight;*/
89 | if(options.outWidth>options.outHeight)
90 | size=options.outWidth;
91 | else size=options.outHeight;
92 | options.inSampleSize = calculateInSampleSize(options, size,
93 | size); // ����inSampleSize
94 | options.inJustDecodeBounds = false;
95 | Bitmap src = BitmapFactory.decodeFile(url, options);
96 | /*return src;*/// ����һ���Դ������ͼ
97 |
98 | /*if(change){
99 | if(options.outWidth>options.outHeight)
100 | return createScaleBitmap(src, reqWidth, reqWidth/re);
101 | else
102 | return createScaleBitmap(src, reqHeight*re, reqHeight);
103 | }
104 | else
105 | return createScaleBitmap(src, reqWidth, reqWidth/re);*/
106 | // ��һ���õ�Ŀ���С������ͼ
107 | return createScaleBitmap(src,(double)reqWidth,reqWidth);
108 | }
109 |
110 | public Bitmap decodeSampledBitmapFromPath(Resources rs, int bm, int reqWidth, int reqHeight,boolean change) throws FileNotFoundException {
111 | final BitmapFactory.Options options = new BitmapFactory.Options();
112 | options.inJustDecodeBounds = true;
113 |
114 |
115 |
116 | BitmapFactory.decodeResource(rs, bm, options);
117 | double re=0;
118 | re= ((double) options.outWidth)/options.outHeight;
119 | options.inSampleSize = calculateInSampleSize(options, reqWidth,
120 | reqHeight); // ����inSampleSize
121 | options.inJustDecodeBounds = false;
122 | Bitmap src = BitmapFactory.decodeResource(rs, bm, options);
123 | /*return src;*/// ����һ���Դ������ͼ
124 |
125 | if(change){
126 | if(options.outWidth>options.outHeight)
127 | return createScaleBitmap(src, reqWidth, reqWidth/re);
128 | else
129 | return createScaleBitmap(src, reqHeight*re, reqHeight);
130 | }
131 | else
132 | return createScaleBitmap(src, reqWidth, reqWidth/re);
133 | // ��һ���õ�Ŀ���С������ͼ
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_setting.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
19 |
20 |
29 |
30 |
36 |
37 |
44 |
45 |
51 |
52 |
58 |
59 |
60 |
61 |
72 |
73 |
74 |
75 |
81 |
82 |
90 |
91 |
99 |
100 |
108 |
109 |
110 |
111 |
119 |
120 |
128 |
129 |
139 |
140 |
150 |
151 |
152 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_user_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
20 |
21 |
25 |
26 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
51 |
52 |
55 |
56 |
63 |
64 |
71 |
72 |
73 |
74 |
77 |
78 |
85 |
86 |
94 |
95 |
96 |
97 |
100 |
101 |
108 |
109 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
135 |
136 |
143 |
144 |
148 |
149 |
150 |
151 |
157 |
158 |
164 |
165 |
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/activity/RankActivity.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.activity;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.os.Bundle;
8 | import android.support.v7.widget.Toolbar;
9 | import android.util.Log;
10 | import android.view.MenuItem;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.widget.BaseAdapter;
14 | import android.widget.ImageView;
15 | import android.widget.ListView;
16 | import android.widget.TextView;
17 | import java.io.IOException;
18 | import java.io.InputStream;
19 | import java.net.HttpURLConnection;
20 | import java.net.MalformedURLException;
21 | import java.net.URL;
22 | import java.util.ArrayList;
23 | import java.util.List;
24 |
25 | import butterknife.Bind;
26 | import butterknife.ButterKnife;
27 | import cn.bmob.v3.BmobQuery;
28 | import cn.bmob.v3.listener.FindListener;
29 | import studio.androiddev.puzzle.R;
30 | import studio.androiddev.puzzle.model.Record;
31 |
32 | public class RankActivity extends BaseActivity {
33 |
34 | @Bind(R.id.toolbar)
35 | Toolbar toolbar;
36 |
37 | ListView mlv_rank;
38 | List mRecSet;
39 | RankAdapter adapter;
40 |
41 | @Override
42 | protected void onCreate(Bundle savedInstanceState) {
43 | super.onCreate(savedInstanceState);
44 | setContentView(R.layout.activity_rank);
45 | ButterKnife.bind(this);
46 | setSupportActionBar(toolbar);
47 |
48 | toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);
49 |
50 | mlv_rank= (ListView) findViewById(R.id.lv_rank);
51 |
52 | BmobQuery query = new BmobQuery<>();
53 | query.order("-updatedAt");
54 | query.setLimit(20);
55 | query.findObjects(this, new FindListener() {
56 | @Override
57 | public void onSuccess(List list) {
58 | mRecSet=list;
59 | adapter=new RankAdapter(mRecSet,RankActivity.this);
60 | mlv_rank.setAdapter(adapter);
61 | }
62 |
63 | @Override
64 | public void onError(int i, String s) {
65 | Log.e("main",s);
66 | }
67 | });
68 |
69 | }
70 |
71 | class RankAdapter extends BaseAdapter{
72 |
73 | ArrayList mSet;
74 | Context context;
75 |
76 | public RankAdapter(List mSett,Context mcontext) {
77 | mSet= (ArrayList) mSett;
78 | context=mcontext;
79 | }
80 |
81 | @Override
82 | public int getCount() {
83 | return mSet.size();
84 | }
85 |
86 | @Override
87 | public Record getItem(int position) {
88 | return mSet.get(position);
89 | }
90 |
91 | @Override
92 | public long getItemId(int position) {
93 | return position;
94 | }
95 |
96 | @Override
97 | public View getView(final int position, View convertView, ViewGroup parent) {
98 |
99 | ViewHolder viewHolder = null;
100 | if (convertView == null) {
101 | convertView = View.inflate(context, R.layout.layout_lv_rank, null);
102 | viewHolder = new ViewHolder();
103 | viewHolder.iv_t= (ImageView) convertView.findViewById(R.id.iv_user_pic);
104 | viewHolder.tv_nick= (TextView) convertView.findViewById(R.id.tv_nickname_rank);
105 | viewHolder.tv_level= (TextView) convertView.findViewById(R.id.tv_level);
106 | viewHolder.tv_gametime= (TextView) convertView.findViewById(R.id.tv_gametime);
107 | viewHolder.tv_uptime= (TextView) convertView.findViewById(R.id.tv_uptime);
108 | convertView.setTag(viewHolder);
109 | } else {
110 | viewHolder = (ViewHolder) convertView.getTag();
111 | }
112 |
113 | // Log.i("main",mSet.toString());
114 |
115 | if (!mSet.get(position).getPic_url().equals("null")) {
116 |
117 | final ViewHolder finalViewHolder = viewHolder;
118 | new Thread(new Runnable() {
119 | @Override
120 | public void run() {
121 | String imageUrl = mSet.get(position).getPic_url();
122 | final Bitmap bitmap = returnBitMap(imageUrl);
123 | runOnUiThread(new Runnable() {
124 | @Override
125 | public void run() {
126 | finalViewHolder.iv_t.setImageBitmap(bitmap);
127 | }
128 | });
129 |
130 | }
131 | }).start();
132 |
133 | }
134 |
135 | String nicktt;
136 | if(!mSet.get(position).getNickname().equals("null")){
137 | nicktt=mSet.get(position).getNickname();
138 | }else {
139 | nicktt=mSet.get(position).getPhoneNum();
140 | }
141 | viewHolder.tv_nick.setText(nicktt);
142 |
143 | viewHolder.tv_level.setText(mSet.get(position).getType() +" x "+mSet.get(position).getType());
144 |
145 | viewHolder.tv_gametime.setText(mSet.get(position).getTime());
146 |
147 | viewHolder.tv_uptime.setText(mSet.get(position).getUpdatedAt());
148 |
149 |
150 | return convertView;
151 | }
152 |
153 |
154 | class ViewHolder {
155 | ImageView iv_t;
156 | TextView tv_nick;
157 | TextView tv_level;
158 | TextView tv_gametime;
159 | TextView tv_uptime;
160 | }
161 |
162 | }
163 |
164 | public Bitmap returnBitMap(String url) {
165 | URL myFileUrl = null;
166 | Bitmap bitmap = null;
167 | try {
168 | myFileUrl = new URL(url);
169 | } catch (MalformedURLException e) {
170 | e.printStackTrace();
171 | }
172 | try {
173 | HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
174 | conn.setDoInput(true);
175 | conn.connect();
176 | InputStream is = conn.getInputStream();
177 | bitmap = BitmapFactory.decodeStream(is);
178 | is.close();
179 | } catch (IOException e) {
180 | e.printStackTrace();
181 | }
182 | return bitmap;
183 | }
184 |
185 |
186 | @Override
187 | public boolean onOptionsItemSelected(MenuItem item) {
188 | if (item.getItemId() == android.R.id.home) {
189 | finish();
190 | return true;
191 | }
192 | return super.onOptionsItemSelected(item);
193 | }
194 |
195 | public static void actionStart(Context context) {
196 | Intent intent = new Intent(context, RankActivity.class);
197 | context.startActivity(intent);
198 | }
199 |
200 |
201 |
202 | }
203 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/activity/GameActivity.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.activity;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.graphics.Bitmap;
7 | import android.os.Bundle;
8 | import android.os.Handler;
9 | import android.os.Message;
10 | import android.support.v7.widget.Toolbar;
11 | import android.util.Log;
12 | import android.view.MenuItem;
13 | import android.view.View;
14 | import android.view.ViewStub;
15 | import android.widget.HorizontalScrollView;
16 | import android.widget.ImageButton;
17 | import android.widget.ImageView;
18 | import android.widget.LinearLayout;
19 | import android.widget.TextView;
20 |
21 | import org.greenrobot.eventbus.EventBus;
22 | import org.greenrobot.eventbus.Subscribe;
23 | import org.greenrobot.eventbus.ThreadMode;
24 |
25 | import java.io.FileNotFoundException;
26 | import java.lang.ref.WeakReference;
27 | import java.util.HashMap;
28 | import java.util.List;
29 |
30 | import butterknife.Bind;
31 | import butterknife.ButterKnife;
32 | import cn.bmob.v3.listener.SaveListener;
33 | import studio.androiddev.puzzle.PuzzleApplication;
34 | import studio.androiddev.puzzle.R;
35 | import studio.androiddev.puzzle.bgm.MusicServer;
36 | import studio.androiddev.puzzle.dish.DishManager;
37 | import studio.androiddev.puzzle.dish.DragImageView;
38 | import studio.androiddev.puzzle.event.DishManagerInitFinishEvent;
39 | import studio.androiddev.puzzle.event.GameSuccessEvent;
40 | import studio.androiddev.puzzle.event.PieceMoveSuccessEvent;
41 | import studio.androiddev.puzzle.event.TimeEvent;
42 | import studio.androiddev.puzzle.imagesplit.ImagePiece;
43 | import studio.androiddev.puzzle.imagesplit.ImageSplitter;
44 | import studio.androiddev.puzzle.model.Record;
45 | import studio.androiddev.puzzle.utils.BitmapUtils;
46 | import studio.androiddev.puzzle.utils.DensityUtil;
47 | import studio.androiddev.puzzle.utils.GameTimer;
48 | import studio.androiddev.puzzle.utils.GlobalUtils;
49 |
50 | public class GameActivity extends BaseActivity {
51 |
52 | @Bind(R.id.toolbar)
53 | Toolbar toolbar;
54 | @Bind(R.id.dish)
55 | ImageView dish;
56 | @Bind(R.id.layViewContainer)
57 | LinearLayout layViewContainer;
58 | @Bind(R.id.gameContainer)
59 | LinearLayout gameContainer;
60 | @Bind(R.id.timeText)
61 | TextView timeText;
62 | @Bind(R.id.viewContainer)
63 | HorizontalScrollView viewContainer;
64 |
65 | private StaticHandler timeHandler = new StaticHandler(GameActivity.this);
66 | private GameTimer gameTimer;
67 | private int time = 0;
68 |
69 | private DishManager dm;
70 | private Bitmap mBitmap;
71 |
72 | private final int DISH_WIDTH = 300;
73 | private final int DISH_HEIGHT = 300;
74 | private HashMap pieceList = new HashMap<>();
75 | private static final String PIC_INDEX = "picIndex";
76 |
77 | private List IPL;
78 |
79 | @Override
80 | protected void onCreate(Bundle savedInstanceState) {
81 | super.onCreate(savedInstanceState);
82 | setContentView(R.layout.activity_game);
83 | ButterKnife.bind(this);
84 | setSupportActionBar(toolbar);
85 | EventBus.getDefault().register(this);
86 | toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);
87 | gameTimer = new GameTimer(timeHandler);
88 |
89 | initialization();
90 | EventBus.getDefault().post(new DishManagerInitFinishEvent());
91 |
92 | }
93 | @Subscribe(threadMode = ThreadMode.MAIN)
94 | public void onEvent(TimeEvent event) {
95 | time++;
96 |
97 | int curminute = time / 60;
98 | int cursecond = time % 60;
99 |
100 | String curTimeString = String.format("%02d:%02d", curminute, cursecond);
101 | timeText.setText(curTimeString);
102 | }
103 |
104 | @Override
105 | protected void onStart() {
106 | super.onStart();
107 |
108 | Intent intent = new Intent(GameActivity.this, MusicServer.class);
109 | startService(intent);
110 |
111 | }
112 |
113 | @Override
114 | protected void onResume() {
115 | super.onResume();
116 | }
117 |
118 | @Override
119 | protected void onStop() {
120 | super.onStop();
121 | Intent intent = new Intent(GameActivity.this, MusicServer.class);
122 | stopService(intent);
123 |
124 | }
125 |
126 | @Override
127 | protected void onDestroy() {
128 | super.onDestroy();
129 | EventBus.getDefault().unregister(this);
130 | if(mBitmap != null && !mBitmap.isRecycled()){
131 | mBitmap.recycle();
132 | }
133 |
134 | dm.recycle();
135 |
136 | if (IPL != null) {
137 | for (int i = 0; i < IPL.size(); i++) {
138 | IPL.get(i).recycleBitmap();
139 | }
140 | IPL.clear();
141 | IPL = null;
142 | }
143 |
144 | if(gameTimer != null){
145 | gameTimer.recycle();
146 | gameTimer = null;
147 | }
148 |
149 | System.gc();
150 | }
151 |
152 | @Subscribe(threadMode = ThreadMode.MAIN)
153 | public void onEvent(PieceMoveSuccessEvent event) {
154 | int index = event.getIndex();
155 | DragImageView view = (DragImageView) pieceList.get(index);
156 | if (view != null) {
157 | view.setVisibility(View.GONE);
158 | }
159 | }
160 |
161 | @Subscribe(threadMode = ThreadMode.MAIN)
162 | public void onEvent(GameSuccessEvent event) {
163 |
164 | gameTimer.stopTimer();
165 | Record eTemp = new Record();
166 |
167 | eTemp.setPhoneNum(PuzzleApplication.getmUser().getPhoneNum());
168 | eTemp.setType(PuzzleApplication.getLevel() + "");
169 | eTemp.setTime(timeText.getText().toString());
170 | eTemp.setPic_url(PuzzleApplication.getmUser().getImgUrl());
171 | eTemp.setNickname(PuzzleApplication.getmUser().getNickName());
172 |
173 | eTemp.save(GameActivity.this, new SaveListener() {
174 | @Override
175 | public void onSuccess() {
176 | Log.i("main", "数据记录保存成功");
177 | }
178 |
179 | @Override
180 | public void onFailure(int i, String s) {
181 | Log.e("main", "数据记录保存失败" + s);
182 | }
183 | });
184 |
185 | showSuccess();
186 |
187 | }
188 |
189 | private void showSuccess() {
190 | viewContainer.setVisibility(View.GONE);
191 | View successContainer = ((ViewStub) findViewById(R.id.success_stub)).inflate();
192 | ImageView finishImage = (ImageView) successContainer.findViewById(R.id.finishImage);
193 | ImageButton againButton = (ImageButton) successContainer.findViewById(R.id.againButton);
194 |
195 | finishImage.setVisibility(View.VISIBLE);
196 | againButton.setVisibility(View.VISIBLE);
197 |
198 | againButton.setOnClickListener(new View.OnClickListener() {
199 | @Override
200 | public void onClick(View v) {
201 | finish();
202 | }
203 | });
204 |
205 | }
206 |
207 | @Subscribe(threadMode = ThreadMode.MAIN)
208 | public void onEvent(DishManagerInitFinishEvent event) {
209 | gameTimer.startTimer();
210 | }
211 |
212 | private void initialization() {
213 | Log.d(TAG, "init begin");
214 | layViewContainer.removeAllViews();
215 | pieceList.clear();
216 |
217 | int picIndex = getIntent().getIntExtra(PIC_INDEX, 0);
218 | mBitmap = BitmapUtils.decodeSampledBitmapFromResources(getResources(),
219 | ChoosePicActivity.icons[picIndex],
220 | DISH_WIDTH, DISH_HEIGHT);
221 | dm = PuzzleApplication.getDishManager();
222 |
223 | if (dm == null) return;
224 |
225 | dm.initNewGame(mBitmap, dish);
226 |
227 | Log.d(TAG, "DishManager init finish");
228 |
229 | try {
230 |
231 | // TODO: 2016/4/27 裁剪算法优化基本完成,尚有几像素的偏差,可能是int到float强制转换的精度损失
232 | //IPL = ImageSplitter.split(mBitmap, PuzzleApplication.getLevel(), DISH_WIDTH, DISH_HEIGHT);
233 | int dishWidth = DensityUtil.dip2px(PuzzleApplication.getAppContext(), DISH_WIDTH);
234 | int dishHeight = DensityUtil.dip2px(PuzzleApplication.getAppContext(), DISH_HEIGHT);
235 | Bitmap tempBitmap = BitmapUtils.createNoRecycleScaleBitmap(
236 | mBitmap,
237 | dishWidth,
238 | dishHeight);
239 | IPL = ImageSplitter.split(tempBitmap, PuzzleApplication.getLevel(),
240 | dishWidth,
241 | dishHeight);
242 | tempBitmap.recycle();
243 | Log.d(TAG, "split finish");
244 |
245 | LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
246 | LinearLayout.LayoutParams.WRAP_CONTENT,
247 | LinearLayout.LayoutParams.WRAP_CONTENT);
248 | layoutParams.setMarginEnd(20);
249 |
250 | int mLevel = PuzzleApplication.getLevel();
251 |
252 | for (int i = 0; i < mLevel; i++) {
253 | for (int j = 0; j < mLevel; j++) {
254 | DragImageView imageView = new DragImageView(this);
255 | imageView.setLayoutParams(layoutParams);
256 | //imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
257 | imageView.setImageBitmap(IPL.get(j + i * mLevel).bitmap);
258 |
259 | imageView.setIndex(j + i * mLevel);
260 | pieceList.put(imageView.getIndex(), imageView);
261 | }
262 | }
263 |
264 | int[] list = GlobalUtils.getRamdomList(mLevel * mLevel);
265 |
266 | if (layViewContainer != null) {
267 | for (int aList : list) {
268 | layViewContainer.addView(pieceList.get(aList), layoutParams);
269 | }
270 |
271 | }
272 |
273 | } catch (FileNotFoundException e) {
274 | e.printStackTrace();
275 | }
276 |
277 | Log.d(TAG, "init finish");
278 | }
279 |
280 |
281 | @Override
282 | public boolean onOptionsItemSelected(MenuItem item) {
283 | if (item.getItemId() == android.R.id.home) {
284 | finish();
285 | return true;
286 | }
287 | return super.onOptionsItemSelected(item);
288 | }
289 |
290 | public static void actionStart(Context context, int picIndex) {
291 | Intent intent = new Intent(context, GameActivity.class);
292 | intent.putExtra(PIC_INDEX, picIndex);
293 | context.startActivity(intent);
294 | }
295 |
296 | public static class StaticHandler extends Handler {
297 |
298 | private final WeakReference mActivity;
299 |
300 | public StaticHandler(Activity activity){
301 | mActivity = new WeakReference(activity);
302 | }
303 |
304 |
305 | @Override
306 | public void handleMessage(Message msg){
307 | super.handleMessage(msg);
308 | switch (msg.what) {
309 | case GameTimer.MESSAGE_TIMER:
310 | EventBus.getDefault().post(new TimeEvent());
311 | //refreshTimeText();
312 | break;
313 |
314 | }
315 | }
316 | }
317 | }
318 |
319 |
320 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/activity/UserInfoActivity.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.activity;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.graphics.Bitmap;
7 | import android.graphics.BitmapFactory;
8 | import android.net.Uri;
9 | import android.os.Bundle;
10 | import android.os.Environment;
11 | import android.provider.MediaStore;
12 | import android.support.v7.widget.Toolbar;
13 | import android.util.Log;
14 | import android.view.Menu;
15 | import android.view.MenuItem;
16 | import android.view.View;
17 | import android.view.ViewGroup;
18 | import android.widget.BaseAdapter;
19 | import android.widget.EditText;
20 | import android.widget.ImageButton;
21 | import android.widget.ImageView;
22 | import android.widget.ListView;
23 | import android.widget.TextView;
24 |
25 | import java.io.File;
26 | import java.io.FileNotFoundException;
27 | import java.io.FileOutputStream;
28 | import java.io.IOException;
29 | import java.io.InputStream;
30 | import java.net.HttpURLConnection;
31 | import java.net.MalformedURLException;
32 | import java.net.URL;
33 | import java.util.List;
34 |
35 | import butterknife.Bind;
36 | import butterknife.ButterKnife;
37 | import butterknife.OnClick;
38 | import cn.bmob.v3.BmobQuery;
39 | import cn.bmob.v3.datatype.BmobFile;
40 | import cn.bmob.v3.listener.FindListener;
41 | import cn.bmob.v3.listener.UpdateListener;
42 | import cn.bmob.v3.listener.UploadFileListener;
43 | import studio.androiddev.puzzle.PuzzleApplication;
44 | import studio.androiddev.puzzle.R;
45 | import studio.androiddev.puzzle.model.Record;
46 | import studio.androiddev.puzzle.model.User;
47 |
48 | public class UserInfoActivity extends BaseActivity {
49 |
50 | private static int CAMERA_REQUEST_CODE = 1;
51 | private static int GALLERY_REQUEST_CODE = 2;
52 | private static int CROP_REQUEST_CODE = 3;
53 |
54 | private static final String IMAGE_FILE_LOCATION = "file:///sdcard/temp.jpg";//temp file
55 | Uri imageUri = Uri.parse(IMAGE_FILE_LOCATION);//The Uri to store the big bitmap
56 |
57 | @Bind(R.id.fresco_logo)
58 | ImageView imageView;
59 | @Bind(R.id.et_nickname)
60 | EditText met_nickname;
61 | @Bind(R.id.met_phone_userinfo)
62 | EditText met_phone;
63 | @Bind(R.id.et_mail)
64 | EditText met_mail;
65 | @Bind(R.id.et_rank)
66 | EditText met_rank;
67 | @Bind(R.id.lv_record)
68 | ListView lv_record;
69 | @Bind(R.id.btn_changePwd)
70 | ImageButton mbtn_changePwd;
71 | @Bind(R.id.btn_exitAccount)
72 | ImageButton mbtn_exit;
73 | @Bind(R.id.toolbar)
74 | Toolbar toolbar;
75 |
76 |
77 | private User user_login; //登陆者账号信息
78 | View inflate;//解析AlertDialog内部布局的view
79 | AlertDialog alertDialog; //更换头像时弹出的对话框
80 | List mRecordSet;
81 | RecordAdapter mAdapter;
82 |
83 | @Override
84 | protected void onCreate(Bundle savedInstanceState) {
85 | super.onCreate(savedInstanceState);
86 | setContentView(R.layout.activity_user_info);
87 | ButterKnife.bind(this);
88 | setSupportActionBar(toolbar);
89 | toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);
90 |
91 | initView();//实例化控件
92 | user_login = PuzzleApplication.getmUser();
93 | setInfo();//为各个控件填充信息
94 |
95 | BmobQuery query = new BmobQuery();
96 | query.setLimit(20);
97 | query.addWhereEqualTo("phoneNum", PuzzleApplication.getmUser().getPhoneNum());
98 | query.findObjects(this, new FindListener() {
99 | @Override
100 | public void onSuccess(List list) {
101 | mRecordSet = list;
102 | mAdapter = new RecordAdapter(mRecordSet, UserInfoActivity.this);
103 | lv_record.setAdapter(mAdapter);
104 | }
105 |
106 | @Override
107 | public void onError(int i, String s) {
108 | Log.e("main", s);
109 | }
110 | });
111 |
112 | AlertDialog.Builder builder = new AlertDialog.Builder(UserInfoActivity.this);
113 | inflate = UserInfoActivity.this.getLayoutInflater().inflate(R.layout.layout_alertdiag, null, false);
114 | builder.setView(inflate);
115 | builder.setTitle("自定义头像");
116 | alertDialog = builder.create();
117 |
118 | findViewById(R.id.fresco_logo).setOnClickListener(new View.OnClickListener() {
119 | @Override
120 | public void onClick(View v) {
121 | alertDialog.show();
122 | }
123 | });
124 |
125 |
126 | inflate.findViewById(R.id.btn_camera_changePic).setOnClickListener(new View.OnClickListener() {
127 | @Override
128 | public void onClick(View v) {
129 | alertDialog.dismiss();
130 | setPicFromCamera();
131 | }
132 | });
133 |
134 | inflate.findViewById(R.id.btn_gallery_changePic).setOnClickListener(new View.OnClickListener() {
135 | @Override
136 | public void onClick(View v) {
137 | alertDialog.dismiss();
138 | setPicFromGallery();
139 | }
140 | });
141 |
142 |
143 | }
144 |
145 |
146 | private void setPicFromGallery() {
147 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
148 | intent.setType("image/*");
149 | startActivityForResult(intent, GALLERY_REQUEST_CODE);
150 | }
151 |
152 | private void setPicFromCamera() {
153 | Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
154 | intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
155 | startActivityForResult(intent, CAMERA_REQUEST_CODE);
156 | }
157 |
158 | private Bitmap decodeUriAsBitmap(Uri uri) {
159 | Bitmap bitmap = null;
160 | try {
161 | bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
162 | } catch (FileNotFoundException e) {
163 | e.printStackTrace();
164 | return null;
165 | }
166 | return bitmap;
167 | }
168 |
169 | private void cropImageUri(Uri uri, int outputX, int outputY, int requestCode) {
170 | Intent intent = new Intent("com.android.camera.action.CROP");
171 | intent.setDataAndType(uri, "image/*");
172 | intent.putExtra("crop", "true");
173 | intent.putExtra("aspectX", 1);
174 | intent.putExtra("aspectY", 1);
175 | intent.putExtra("outputX", outputX);
176 | intent.putExtra("outputY", outputY);
177 | intent.putExtra("scale", true);
178 | intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
179 | intent.putExtra("return-data", false);
180 | intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
181 | intent.putExtra("noFaceDetection", true); // no face detection
182 | startActivityForResult(intent, requestCode);
183 | }
184 |
185 | private void setInfo() {
186 | met_phone.setText(PuzzleApplication.getmUser().getPhoneNum());
187 | met_nickname.setText(PuzzleApplication.getmUser().getNickName());
188 | met_mail.setText(PuzzleApplication.getmUser().getMailNum());
189 | if (!user_login.getImgUrl().equals("null")) {
190 |
191 | new Thread(new Runnable() {
192 | @Override
193 | public void run() {
194 | String imageUrl = user_login.getImgUrl();
195 | final Bitmap bitmap = returnBitMap(imageUrl);
196 | runOnUiThread(new Runnable() {
197 | @Override
198 | public void run() {
199 | imageView.setImageBitmap(bitmap);
200 | }
201 | });
202 |
203 | }
204 | }).start();
205 | }
206 | }
207 |
208 | public Bitmap returnBitMap(String url) {
209 |
210 | URL myFileUrl = null;
211 | Bitmap bitmap = null;
212 | try {
213 | myFileUrl = new URL(url);
214 | } catch (MalformedURLException e) {
215 | e.printStackTrace();
216 | }
217 | try {
218 | HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
219 | conn.setDoInput(true);
220 | conn.connect();
221 | InputStream is = conn.getInputStream();
222 | bitmap = BitmapFactory.decodeStream(is);
223 | is.close();
224 | } catch (IOException e) {
225 | e.printStackTrace();
226 | }
227 | return bitmap;
228 | }
229 |
230 |
231 | private void initView() {
232 | met_mail.setEnabled(false);
233 | met_rank.setEnabled(false);
234 | met_phone.setEnabled(false);
235 | met_nickname.setEnabled(false);
236 | met_rank.setText("第一名");
237 | }
238 |
239 |
240 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
241 |
242 | if (requestCode == CAMERA_REQUEST_CODE) {
243 | cropImageUri(imageUri, 300, 300, CROP_REQUEST_CODE);
244 | } else if (requestCode == GALLERY_REQUEST_CODE) {
245 |
246 | if (data == null) {
247 | return;
248 | }
249 | Uri uri = data.getData();//content类型的uri
250 | Intent intent = new Intent("com.android.camera.action.CROP");
251 | intent.setDataAndType(uri, "image/*");
252 | intent.putExtra("crop", "true");
253 | intent.putExtra("aspectX", 1);
254 | intent.putExtra("aspectY", 1);
255 | intent.putExtra("outputX", 300);
256 | intent.putExtra("outputY", 300);
257 | intent.putExtra("return-data", false);
258 | intent.putExtra("scale", true);
259 | intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
260 | intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
261 | intent.putExtra("noFaceDetection", true); // no face detection
262 | startActivityForResult(intent, CROP_REQUEST_CODE);
263 |
264 | } else if (requestCode == CROP_REQUEST_CODE) {
265 |
266 | if (imageUri != null) {
267 | Bitmap bitmap = decodeUriAsBitmap(imageUri);//decode bitmap
268 | imageView.setImageBitmap(bitmap);
269 | File tempDir = new File(Environment.getExternalStorageDirectory() + "");
270 | String picPath = tempDir.getAbsolutePath() + "/temp.jpg";
271 | final BmobFile bmobFile = new BmobFile(new File(picPath));
272 |
273 | bmobFile.uploadblock(UserInfoActivity.this, new UploadFileListener() {
274 | @Override
275 | public void onSuccess() {
276 |
277 | user_login.setImgUrl(bmobFile.getFileUrl(UserInfoActivity.this));
278 | String obId = user_login.getObjectId();
279 | user_login.update(UserInfoActivity.this, obId, new UpdateListener() {
280 | @Override
281 | public void onSuccess() {
282 | Log.i("main", "更新头像URL成功");
283 | }
284 |
285 | @Override
286 | public void onFailure(int i, String s) {
287 | Log.e("main", s);
288 |
289 | }
290 | });
291 | }
292 |
293 | @Override
294 | public void onProgress(Integer value) {
295 | // 返回的上传进度(百分比)
296 | }
297 |
298 | @Override
299 | public void onFailure(int code, String msg) {
300 | Log.e("main", msg);
301 | }
302 | });
303 |
304 | }
305 |
306 |
307 | } else if (requestCode == 1234) {
308 | if (data == null) {
309 |
310 | } else {
311 | User mReUser = (User) data.getSerializableExtra("reuser");
312 | user_login = mReUser;
313 | PuzzleApplication.setmUser(mReUser);
314 | }
315 |
316 | }
317 |
318 | }
319 |
320 |
321 | @Override
322 | public boolean onCreateOptionsMenu(Menu menu) {
323 | getMenuInflater().inflate(R.menu.menu_user_info, menu);
324 | return true;
325 | }
326 |
327 | @Override
328 | public boolean onOptionsItemSelected(MenuItem item) {
329 | int id = item.getItemId();
330 |
331 | if (id == R.id.menuItem_edit) {
332 | CharSequence title = item.getTitle();
333 | if (item.getTitle().equals("编辑")) {
334 | item.setTitle("保存");
335 | met_nickname.setEnabled(true);
336 | met_mail.setEnabled(true);
337 |
338 | } else {
339 | item.setTitle("编辑");
340 | met_nickname.setEnabled(false);
341 | met_mail.setEnabled(false);
342 | if (!(user_login.getMailNum().equals(met_mail.getText().toString()) && user_login.getNickName().equals(met_nickname.getText().toString()))) {
343 | user_login.setNickName(met_nickname.getText().toString());
344 | user_login.setMailNum(met_mail.getText().toString());
345 | user_login.update(UserInfoActivity.this, user_login.getObjectId(), new UpdateListener() {
346 | @Override
347 | public void onSuccess() {
348 | }
349 |
350 | @Override
351 | public void onFailure(int i, String s) {
352 | }
353 | });
354 | }
355 | }
356 | return true;
357 | } else if (item.getItemId() == android.R.id.home) {
358 | finish();
359 | return true;
360 | }
361 |
362 | return super.onOptionsItemSelected(item);
363 | }
364 |
365 | @OnClick({R.id.btn_changePwd, R.id.btn_exitAccount})
366 | public void onClick(View view) {
367 | switch (view.getId()) {
368 | case R.id.btn_changePwd:
369 | ChangePwdActivity.actionStart(UserInfoActivity.this);
370 | break;
371 | case R.id.btn_exitAccount:
372 | LoginActivity.actionStart(UserInfoActivity.this);
373 | finish();
374 | break;
375 | }
376 | }
377 |
378 | class RecordAdapter extends BaseAdapter {
379 |
380 | List mSet;
381 | Context mContext;
382 |
383 | public RecordAdapter(List mSet, Context mContext) {
384 | this.mSet = mSet;
385 | this.mContext = mContext;
386 | }
387 |
388 | @Override
389 | public int getCount() {
390 | return mSet.size();
391 | }
392 |
393 | @Override
394 | public Record getItem(int position) {
395 | return mSet.get(position);
396 | }
397 |
398 | @Override
399 | public long getItemId(int position) {
400 | return position;
401 | }
402 |
403 | @Override
404 | public View getView(int position, View convertView, ViewGroup parent) {
405 | ViewHolder viewHolder = null;
406 | if (convertView == null) {
407 | convertView = View.inflate(mContext, R.layout.layout_record, null);
408 | viewHolder = new ViewHolder();
409 | viewHolder.mtv_type = (TextView) convertView.findViewById(R.id.tv_lv_record_type);
410 | viewHolder.mtv_time = (TextView) convertView.findViewById(R.id.tv_lv_record_time);
411 | convertView.setTag(viewHolder);
412 | } else {
413 | viewHolder = (ViewHolder) convertView.getTag();
414 | }
415 |
416 | viewHolder.mtv_time.setText(getItem(position).getTime());
417 | viewHolder.mtv_type.setText(getItem(position).getType() + " x " + getItem(position).getType());
418 | if (position % 2 == 0) {
419 | convertView.findViewById(R.id.linearlayout_record).setBackgroundColor(getResources().getColor(R.color.personGreyDark));
420 | }
421 | return convertView;
422 | }
423 |
424 |
425 | class ViewHolder {
426 | TextView mtv_type;
427 | TextView mtv_time;
428 | }
429 | }
430 |
431 | public static void actionStart(Context context) {
432 | Intent intent = new Intent(context, UserInfoActivity.class);
433 | context.startActivity(intent);
434 | }
435 |
436 | }
437 |
--------------------------------------------------------------------------------
/app/src/main/java/studio/androiddev/puzzle/dish/DishManager.java:
--------------------------------------------------------------------------------
1 | package studio.androiddev.puzzle.dish;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.graphics.PorterDuff;
8 | import android.graphics.PorterDuffXfermode;
9 | import android.graphics.RectF;
10 | import android.util.Log;
11 | import android.view.DragEvent;
12 | import android.view.View;
13 | import android.widget.ImageView;
14 |
15 | import org.greenrobot.eventbus.EventBus;
16 |
17 | import studio.androiddev.puzzle.PuzzleApplication;
18 | import studio.androiddev.puzzle.event.GameSuccessEvent;
19 | import studio.androiddev.puzzle.event.PieceMoveSuccessEvent;
20 | import studio.androiddev.puzzle.utils.DensityUtil;
21 |
22 | /**
23 | * puzzle
24 | * 拼盘管理类,用于更新拼盘的显示
25 | * Created by ZQ on 2016/4/3.
26 | */
27 | public class DishManager{
28 |
29 | private static final String TAG = "puzzle";
30 |
31 | //拼盘
32 | private ImageView mImageView;
33 | //游戏难度
34 | private int mLevel;
35 | //拼图图片
36 | private Bitmap mBitmap;
37 | //拼图数组
38 | private boolean[] mIndex;
39 | //拼块数目
40 | private int mSize;
41 | //距离游戏胜利还需移动的拼块数目
42 | private int mLeftSize;
43 | //拼盘大小
44 | private static int DISH_HEIGHT = 300;
45 | private static int DISH_WIDTH = 300;
46 |
47 | //基本款遮罩拼块
48 | //private static Bitmap[] bmcover = new Bitmap[9];
49 | public static final int COVER_CENTER = 0;
50 | public static final int COVER_TOP = 1;
51 | public static final int COVER_BOTTOM = 2;
52 | public static final int COVER_LEFT = 3;
53 | public static final int COVER_RIGHT = 4;
54 | public static final int COVER_TOP_LEFT = 5;
55 | public static final int COVER_TOP_RIGHT = 6;
56 | public static final int COVER_BOTTOM_LEFT = 7;
57 | public static final int COVER_BOTTOM_RIGHT = 8;
58 | //拼块凹凸半径
59 | private static float r;
60 | //拼块内的矩形长宽
61 | private static float rectWidth;
62 | private static float rectHeight;
63 | //拼块的长宽
64 | static float width;
65 | static float height;
66 |
67 | public DishManager(int level){
68 | mLevel = level;
69 | mSize = level * level;
70 | mLeftSize = mSize;
71 | mIndex = new boolean[mSize];
72 | for(int i = 0; i < mSize; i++) mIndex[i] = false;
73 |
74 | p = new Paint();
75 | p.setColor(Color.RED);
76 |
77 | pOut = new Paint();
78 | pOut.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
79 | pOut.setAntiAlias(true);
80 | pOut.setColor(Color.RED);
81 |
82 | pOver = new Paint();
83 | pOver.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
84 | pOver.setAntiAlias(true);
85 | pOver.setColor(Color.RED);
86 |
87 | initMask();
88 | }
89 |
90 | /**
91 | * 游戏结束后调用,释放资源
92 | */
93 | public void recycle(){
94 | if(mImageView != null) {
95 | mImageView = null;
96 | }
97 | if(mBitmap != null && !mBitmap.isRecycled()){
98 | mBitmap.recycle();
99 | }
100 |
101 | }
102 |
103 | /**
104 | * 初始化新游戏
105 | * @param bitmap 新游戏图片
106 | * @param imageView 新游戏的拼盘
107 | */
108 | public void initNewGame(Bitmap bitmap, ImageView imageView){
109 | if(bitmap == null || imageView == null) return;
110 |
111 | if(mBitmap != null && !mBitmap.isRecycled()){
112 | mBitmap.recycle();
113 | }
114 |
115 | mImageView = imageView;
116 | mBitmap = bitmap;
117 | mLeftSize = mSize;
118 | for(int i = 0; i < mIndex.length; i++){
119 | mIndex[i] = false;
120 | }
121 |
122 | imageView.setOnDragListener(new View.OnDragListener() {
123 | @Override
124 | public boolean onDrag(View v, DragEvent event) {
125 | int x = (int) event.getX();
126 | int y = (int) event.getY();
127 | int index = (int) event.getLocalState();
128 |
129 | switch (event.getAction()){
130 | case DragEvent.ACTION_DRAG_STARTED:
131 |
132 | break;
133 | case DragEvent.ACTION_DRAG_ENTERED:
134 |
135 | break;
136 | case DragEvent.ACTION_DRAG_EXITED:
137 |
138 | break;
139 | case DragEvent.ACTION_DRAG_ENDED:
140 |
141 | break;
142 | case DragEvent.ACTION_DROP:
143 |
144 | if(judgeDrag(index, x, y)){
145 | updatePiece(index);
146 | }
147 |
148 | break;
149 | default:
150 | break;
151 | }
152 |
153 | return true;
154 | }
155 | });
156 |
157 | refreshDish();
158 | }
159 |
160 | public void setBitmap(Bitmap bitmap){
161 | mBitmap = bitmap;
162 | }
163 |
164 | public void setLevel(int level){
165 | mLevel = level;
166 | }
167 |
168 | // public static Bitmap[] getBitmapCover() {
169 | // return bmcover;
170 | // }
171 |
172 | public static Bitmap getCover(int index){
173 | Bitmap bitmap = Bitmap.createBitmap(
174 | (int) width,
175 | (int) height,
176 | Bitmap.Config.ARGB_8888);
177 |
178 | Canvas canvas = new Canvas(bitmap);
179 |
180 | switch (index){
181 | case COVER_TOP_LEFT:
182 | canvas.drawRect(0, 0, rectWidth, rectHeight, p);
183 | canvas.drawArc(ovalRight, 0, 360, true, pOut);
184 | canvas.drawArc(ovalBottom, 0, 360, true, pOver);
185 | break;
186 | case COVER_TOP:
187 | canvas.drawRect(r, 0, r + rectWidth, rectHeight, p);
188 | canvas.drawArc(ovalLeft, 0, 360, true, pOver);
189 | canvas.drawArc(ovalBottomRight, 0, 360, true, pOver);
190 | canvas.drawArc(ovalRightRight, 0, 360, true, pOut);
191 | break;
192 | case COVER_TOP_RIGHT:
193 | canvas.drawRect(r, 0, r + rectWidth, rectHeight, p);
194 | canvas.drawArc(ovalLeft, 0, 360, true, pOver);
195 | canvas.drawArc(ovalBottomRight, 0, 360, true, pOver);
196 | break;
197 | case COVER_LEFT:
198 | canvas.drawRect(0, 0, rectWidth, rectHeight, p);
199 | canvas.drawArc(ovalBottom, 0, 360, true, pOver);
200 | canvas.drawArc(ovalTop, 0, 360, true, pOut);
201 | canvas.drawArc(ovalRight, 0, 360, true, pOut);
202 | break;
203 | case COVER_CENTER:
204 | canvas.drawRect(r, 0, r + rectWidth, rectHeight, p);
205 | canvas.drawArc(ovalTopRight, 0, 360, true, pOut);
206 | canvas.drawArc(ovalRightRight, 0, 360, true, pOut);
207 | canvas.drawArc(ovalLeft, 0, 360, true, pOver);
208 | canvas.drawArc(ovalBottomRight, 0, 360, true, pOver);
209 | break;
210 | case COVER_BOTTOM_LEFT:
211 | canvas.drawRect(0, 0, rectWidth, rectHeight, p);
212 | canvas.drawArc(ovalTop, 0, 360, true, pOut);
213 | canvas.drawArc(ovalRight, 0, 360, true, pOut);
214 | break;
215 | case COVER_BOTTOM:
216 | canvas.drawRect(r, 0, rectWidth + r, rectHeight, p);
217 | canvas.drawArc(ovalLeft, 0, 360, true, pOver);
218 | canvas.drawArc(ovalTopRight, 0, 360, true, pOut);
219 | canvas.drawArc(ovalRightRight, 0, 360, true, pOut);
220 | break;
221 | case COVER_BOTTOM_RIGHT:
222 | canvas.drawRect(r, 0, rectWidth + r, rectHeight, p);
223 | canvas.drawArc(ovalLeft, 0, 360, true, pOver);
224 | canvas.drawArc(ovalTopRight, 0, 360, true, pOut);
225 | break;
226 | case COVER_RIGHT:
227 | canvas.drawRect(r, 0, rectWidth + r, rectHeight, p);
228 | canvas.drawArc(ovalTopRight, 0, 360, true, pOut);
229 | canvas.drawArc(ovalLeft, 0, 360, true, pOver);
230 | canvas.drawArc(ovalBottomRight, 0, 360, true, pOver);
231 | }
232 |
233 | canvas.save();
234 | return bitmap;
235 | }
236 |
237 | /**
238 | * 判断拼块是否被拖动到正确的位置
239 | * @param i 拼块下标
240 | * @param x 拖动事件x坐标
241 | * @param y 拖动事件y坐标
242 | * @return 判断结果
243 | */
244 | public boolean judgeDrag(int i, int x, int y){
245 | RectF rect = getRectF(i);
246 | return rect.contains(x, y);
247 | }
248 |
249 | /**
250 | * 根据拼块下标计算拼块实际占据的方形大小
251 | * @param i 拼块下标
252 | * @return 拼块实际占据的方形大小
253 | */
254 | private RectF getRectF(int i){
255 |
256 | return new RectF(
257 | (i % mLevel) * rectWidth,
258 | (i / mLevel) * rectHeight,
259 | (i % mLevel + 1) * rectWidth,
260 | (i / mLevel + 1) * rectHeight);
261 | }
262 |
263 | /**
264 | * 当玩家将拼块移动到正确位置时调用,更新拼盘显示状态
265 | * @param i 正确的拼块下标
266 | */
267 | public void updatePiece(int i){
268 | if(i < 0 || i > mLevel * mLevel) return;
269 |
270 | mIndex[i] = true;
271 | refreshDish();
272 | EventBus.getDefault().post(new PieceMoveSuccessEvent(i));
273 | mLeftSize--;
274 | if(mLeftSize == 0){
275 | EventBus.getDefault().post(new GameSuccessEvent());
276 | }
277 | }
278 |
279 | /**
280 | * 根据拼盘大小和游戏难度初始化基本遮罩拼块
281 | */
282 | private void initMask(){
283 |
284 | rectWidth = DensityUtil.dip2px(PuzzleApplication.getAppContext(), (float) DISH_WIDTH / mLevel);
285 | rectHeight = DensityUtil.dip2px(PuzzleApplication.getAppContext(), (float) DISH_HEIGHT / mLevel);
286 | r = rectWidth / 4;
287 |
288 | Log.d(TAG, "rectWidth and Height: " + rectWidth);
289 |
290 | width = rectWidth + r;
291 | height = rectHeight + r;
292 |
293 | ovalLeft = new RectF(0, rectHeight / 2 - r, 2 * r, rectHeight / 2 + r);
294 | ovalTop = new RectF(rectWidth / 2 - r, - r, rectWidth / 2 + r, r);
295 | ovalTopRight = new RectF(rectWidth / 2, - r, rectWidth / 2 + 2 * r, r);
296 | ovalRight = new RectF(rectWidth - r, rectHeight / 2 - r, rectWidth + r, rectHeight / 2 + r);
297 | ovalBottom = new RectF(rectWidth / 2 - r, rectHeight - r, rectWidth / 2 + r, rectHeight + r);
298 | ovalRightRight = new RectF(rectWidth, rectHeight / 2 - r, rectWidth + 2 * r, rectHeight / 2 + r);
299 | ovalBottomRight = new RectF(rectWidth / 2, rectHeight - r, rectWidth / 2 + 2 * r, rectHeight + r);
300 |
301 | // for(int i = 0; i < 9; i++){
302 | // if(bmcover[i] != null){
303 | // bmcover[i].recycle();
304 | // bmcover[i] = null;
305 | // }
306 | // System.gc();
307 | // }
308 |
309 | // for(int i = 0; i < 9; i++){
310 | // bmcover[i] = Bitmap.createBitmap(
311 | // (int) width,
312 | // (int) height,
313 | // Bitmap.Config.ARGB_8888);
314 | // }
315 | //
316 | // Paint p = new Paint();
317 | // p.setColor(Color.RED);
318 | //
319 | // Paint pOut = new Paint();
320 | // pOut.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
321 | // pOut.setAntiAlias(true);
322 | // pOut.setColor(Color.RED);
323 | //
324 | // Paint pOver = new Paint();
325 | // pOver.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
326 | // pOver.setAntiAlias(true);
327 | // pOver.setColor(Color.RED);
328 | //
329 | // RectF ovalLeft = new RectF(0, rectHeight / 2 - r, 2 * r, rectHeight / 2 + r);
330 | // RectF ovalTop = new RectF(rectWidth / 2 - r, - r, rectWidth / 2 + r, r);
331 | // RectF ovalTopRight = new RectF(rectWidth / 2, - r, rectWidth / 2 + 2 * r, r);
332 | // RectF ovalRight = new RectF(rectWidth - r, rectHeight / 2 - r, rectWidth + r, rectHeight / 2 + r);
333 | // RectF ovalBottom = new RectF(rectWidth / 2 - r, rectHeight - r, rectWidth / 2 + r, rectHeight + r);
334 | // RectF ovalRightRight = new RectF(rectWidth, rectHeight / 2 - r, rectWidth + 2 * r, rectHeight / 2 + r);
335 | // RectF ovalBottomRight = new RectF(rectWidth / 2, rectHeight - r, rectWidth / 2 + 2 * r, rectHeight + r);
336 | //
337 | // Canvas canvas = new Canvas(bmcover[COVER_TOP_LEFT]);
338 | // canvas.drawRect(0, 0, rectWidth, rectHeight, p);
339 | // canvas.drawArc(ovalRight, 0, 360, true, pOut);
340 | // canvas.drawArc(ovalBottom, 0, 360, true, pOver);
341 | // canvas.save();
342 | //
343 | // canvas.setBitmap(bmcover[COVER_TOP]);
344 | // canvas.drawRect(r, 0, r + rectWidth, rectHeight, p);
345 | // canvas.drawArc(ovalLeft, 0, 360, true, pOver);
346 | // canvas.drawArc(ovalBottomRight, 0, 360, true, pOver);
347 | // canvas.drawArc(ovalRightRight, 0, 360, true, pOut);
348 | // canvas.save();
349 | //
350 | // canvas.setBitmap(bmcover[COVER_TOP_RIGHT]);
351 | // canvas.drawRect(r, 0, r + rectWidth, rectHeight, p);
352 | // canvas.drawArc(ovalLeft, 0, 360, true, pOver);
353 | // canvas.drawArc(ovalBottomRight, 0, 360, true, pOver);
354 | // canvas.save();
355 | //
356 | // canvas.setBitmap(bmcover[COVER_LEFT]);
357 | // canvas.drawRect(0, 0, rectWidth, rectHeight, p);
358 | // canvas.drawArc(ovalBottom, 0, 360, true, pOver);
359 | // canvas.drawArc(ovalTop, 0, 360, true, pOut);
360 | // canvas.drawArc(ovalRight, 0, 360, true, pOut);
361 | // canvas.save();
362 | //
363 | // canvas.setBitmap(bmcover[COVER_CENTER]);
364 | // canvas.drawRect(r, 0, r + rectWidth, rectHeight, p);
365 | // canvas.drawArc(ovalTopRight, 0, 360, true, pOut);
366 | // canvas.drawArc(ovalRightRight, 0, 360, true, pOut);
367 | // canvas.drawArc(ovalLeft, 0, 360, true, pOver);
368 | // canvas.drawArc(ovalBottomRight, 0, 360, true, pOver);
369 | // canvas.save();
370 | //
371 | // canvas.setBitmap(bmcover[COVER_BOTTOM_LEFT]);
372 | // canvas.drawRect(0, 0, rectWidth, rectHeight, p);
373 | // canvas.drawArc(ovalTop, 0, 360, true, pOut);
374 | // canvas.drawArc(ovalRight, 0, 360, true, pOut);
375 | // canvas.save();
376 | //
377 | // canvas.setBitmap(bmcover[COVER_BOTTOM]);
378 | // canvas.drawRect(r, 0, rectWidth + r, rectHeight, p);
379 | // canvas.drawArc(ovalLeft, 0, 360, true, pOver);
380 | // canvas.drawArc(ovalTopRight, 0, 360, true, pOut);
381 | // canvas.drawArc(ovalRightRight, 0, 360, true, pOut);
382 | // canvas.save();
383 | //
384 | // canvas.setBitmap(bmcover[COVER_BOTTOM_RIGHT]);
385 | // canvas.drawRect(r, 0, rectWidth + r, rectHeight, p);
386 | // canvas.drawArc(ovalLeft, 0, 360, true, pOver);
387 | // canvas.drawArc(ovalTopRight, 0, 360, true, pOut);
388 | // canvas.save();
389 | //
390 | // canvas.setBitmap(bmcover[COVER_RIGHT]);
391 | // canvas.drawRect(r, 0, rectWidth + r, rectHeight, p);
392 | // canvas.drawArc(ovalTopRight, 0, 360, true, pOut);
393 | // canvas.drawArc(ovalLeft, 0, 360, true, pOver);
394 | // canvas.drawArc(ovalBottomRight, 0, 360, true, pOver);
395 | // canvas.save();
396 |
397 | }
398 | private static Paint p, pOut, pOver;
399 | private static RectF ovalLeft, ovalTop, ovalTopRight, ovalRight, ovalBottom, ovalRightRight, ovalBottomRight;
400 |
401 | /**
402 | * 根据当前游戏进度生成遮罩层
403 | * @return 遮罩层Bitmap
404 | */
405 | private Bitmap getMask(){
406 | int width = DensityUtil.dip2px(PuzzleApplication.getAppContext(), (float) DISH_WIDTH);
407 | int height = DensityUtil.dip2px(PuzzleApplication.getAppContext(), (float) DISH_HEIGHT);
408 | Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
409 | Canvas canvas = new Canvas(mask);
410 |
411 | Paint p = new Paint();
412 | p.setAntiAlias(true);
413 | p.setColor(Color.RED);
414 |
415 | for(int i = 0; i < mSize; i += mLevel){
416 | for(int j = i; j < i + mLevel; j++){
417 | if(!mIndex[j]) continue;
418 |
419 | Bitmap cover;
420 |
421 | //最右一列
422 | if((j + 1) % mLevel == 0) {
423 | //右上角
424 | if(j == mLevel - 1) {
425 | cover = getCover(COVER_TOP_RIGHT);
426 | canvas.drawBitmap(cover, rectWidth * (mLevel - 1) - r, 0, p);
427 | }
428 | //右下角
429 | else if (j == mSize - 1){
430 | cover = getCover(COVER_BOTTOM_RIGHT);
431 | canvas.drawBitmap(
432 | cover,
433 | rectWidth * (mLevel - 1) - r,
434 | rectHeight * (mLevel - 1), p);
435 | }
436 | else{
437 | cover = getCover(COVER_RIGHT);
438 | canvas.drawBitmap(cover,
439 | rectWidth * (mLevel - 1) - r,
440 | rectHeight * (i / mLevel), p);
441 | }
442 |
443 | }
444 | //最左一列
445 | else if(j % mLevel == 0) {
446 | //左上角
447 | if(j == 0){
448 | cover = getCover(COVER_TOP_LEFT);
449 | canvas.drawBitmap(cover, 0, 0, p);
450 | }
451 | //左下角
452 | if(j == mSize - mLevel + 1){
453 | cover = getCover(COVER_BOTTOM_LEFT);
454 | canvas.drawBitmap(cover,
455 | 0,
456 | rectHeight * (mLevel - 1), p);
457 | }
458 |
459 | else{
460 | cover = getCover(COVER_LEFT);
461 | canvas.drawBitmap(cover,
462 | 0,
463 | rectHeight * (i / mLevel), p);
464 | }
465 | }
466 | //最上一行
467 | else if(j < mLevel){
468 | cover = getCover(COVER_TOP);
469 | canvas.drawBitmap(cover,
470 | rectWidth * j - r,
471 | 0, p);
472 | }
473 | //最下一行
474 | else if(j > (mSize - mLevel)){
475 | cover = getCover(COVER_BOTTOM);
476 | canvas.drawBitmap(cover,
477 | rectWidth * (j % mLevel) - r,
478 | rectHeight * (mLevel - 1), p);
479 | }
480 | //中间
481 | else{
482 | cover = getCover(COVER_CENTER);
483 | canvas.drawBitmap(cover,
484 | rectWidth * (j % mLevel) - r,
485 | rectHeight * (i / mLevel), p);
486 | }
487 |
488 | cover.recycle();
489 |
490 | }
491 |
492 | }
493 |
494 | canvas.save();
495 |
496 | return mask;
497 | }
498 |
499 | private Bitmap output;
500 | private Bitmap mask;
501 | /**
502 | * 刷新拼盘显示
503 | * 首先获取遮罩层,然后将遮罩层与原始图片混合并显示
504 | */
505 | private void refreshDish(){
506 | if(mBitmap == null) return;
507 | if(mask != null) mask.recycle();
508 | if(output != null) output.recycle();
509 | //获取遮罩层
510 | mask = getMask();
511 |
512 | //将遮罩层与原始图片混合并显示在ImageView
513 | int width = DensityUtil.dip2px(PuzzleApplication.getAppContext(), (float) DISH_WIDTH);
514 | int height = DensityUtil.dip2px(PuzzleApplication.getAppContext(), (float) DISH_HEIGHT);
515 | output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
516 | Paint p = new Paint();
517 |
518 | p.setAntiAlias(true);
519 | Canvas canvas = new Canvas(output);
520 | canvas.drawBitmap(mask, 0, 0, p);
521 | p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
522 | RectF rect = new RectF(0, 0, width, height);
523 | canvas.drawBitmap(mBitmap, null, rect, p);
524 | mImageView.setImageBitmap(output);
525 | }
526 |
527 | }
528 |
--------------------------------------------------------------------------------