├── .gitignore ├── LICENCE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── xiaopo │ │ └── flying │ │ └── stickerview │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── com │ │ │ └── xiaopo │ │ │ └── flying │ │ │ └── stickerview │ │ │ ├── HelloIconEvent.java │ │ │ ├── MainActivity.java │ │ │ └── util │ │ │ └── FileUtil.java │ └── res │ │ ├── drawable-hdpi │ │ └── ic_favorite_white_24dp.png │ │ ├── drawable-mdpi │ │ └── ic_favorite_white_24dp.png │ │ ├── drawable-nodpi │ │ ├── border.png │ │ ├── bubble.png │ │ ├── haizewang_215.png │ │ ├── haizewang_23.png │ │ └── haizewang_90.png │ │ ├── drawable-xhdpi │ │ └── ic_favorite_white_24dp.png │ │ ├── drawable-xxhdpi │ │ └── ic_favorite_white_24dp.png │ │ ├── drawable-xxxhdpi │ │ └── ic_favorite_white_24dp.png │ │ ├── layout │ │ └── activity_main.xml │ │ ├── menu │ │ └── menu_save.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── xiaopo │ └── flying │ └── stickerview │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── screenshot1.png └── screenshot2.png ├── settings.gradle └── sticker ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml ├── java └── com │ └── xiaopo │ └── flying │ └── sticker │ ├── AbstractFlipEvent.java │ ├── BitmapStickerIcon.java │ ├── DeleteIconEvent.java │ ├── DrawableSticker.java │ ├── FlipBothDirectionsEvent.java │ ├── FlipHorizontallyEvent.java │ ├── FlipVerticallyEvent.java │ ├── Sticker.java │ ├── StickerIconEvent.java │ ├── StickerUtils.java │ ├── StickerView.java │ ├── TextSticker.java │ └── ZoomIconEvent.java └── res ├── drawable-hdpi ├── sticker_ic_close_white_18dp.png ├── sticker_ic_flip_white_18dp.png └── sticker_ic_scale_white_18dp.png ├── drawable-mdpi ├── sticker_ic_close_white_18dp.png ├── sticker_ic_flip_white_18dp.png └── sticker_ic_scale_white_18dp.png ├── drawable-xhdpi ├── sticker_ic_close_white_18dp.png ├── sticker_ic_flip_white_18dp.png └── sticker_ic_scale_white_18dp.png ├── drawable-xxhdpi ├── sticker_ic_close_white_18dp.png ├── sticker_ic_flip_white_18dp.png └── sticker_ic_scale_white_18dp.png ├── drawable-xxxhdpi ├── sticker_ic_close_white_18dp.png ├── sticker_ic_flip_white_18dp.png └── sticker_ic_scale_white_18dp.png ├── drawable └── sticker_transparent_background.xml └── values ├── attrs.xml └── strings.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .DS_Store 5 | /build 6 | /captures 7 | .externalNativeBuild 8 | /.idea/ 9 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2016 wuapnjie 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-StickerView-brightgreen.svg?style=flat)]() 2 | StickerView 3 | ========= 4 | 5 | A view which can add sticker and zoom,drag,flip,delete it 6 | 7 | **I hope you can copy the source code to your project so you can design your own function.** 8 | 9 | ## Screenshots 10 | ![](https://github.com/wuapnjie/StickerView/blob/master/screenshots/screenshot1.png) 11 | ![](https://github.com/wuapnjie/StickerView/blob/master/screenshots/screenshot2.png) 12 | 13 | ## Usage 14 | 15 | **Suggestion** 16 | 17 | **copy the source code to your project so you can design your own function.** 18 | 19 | 20 | **Tips**:StickerView extends FrameLayout 21 | #### In layout 22 | ```xml 23 | 28 | 29 | 33 | 34 | ``` 35 | #### Add sticker 36 | If the sticker is drawable, it's intrinsic width and height can not be zero. 37 | If the sticker is text, you can set text color, font and alignment and the region which holds the text. 38 | 39 | ```java 40 | stickerView.addSticker(sticker) 41 | stickerView.replace(sticker) 42 | stickerView.remove(sticker) 43 | stickerView.removeCurrentSticker() 44 | stickerView.removeAllStickers() 45 | stcikerView.setLocked(true) 46 | ``` 47 | 48 | Also you can custom the icon and icon event and position 49 | 50 | ```java 51 | BitmapStickerIcon heartIcon = 52 | new BitmapStickerIcon(ContextCompat.getDrawable(this, R.drawable.ic_favorite_white_24dp), 53 | BitmapStickerIcon.LEFT_BOTTOM); 54 | heartIcon.setIconEvent(new HelloIconEvent()); 55 | 56 | stickerView.setIcons(Arrays.asList(deleteIcon, zoomIcon, flipIcon, heartIcon)); 57 | ``` 58 | 59 | ## Update 60 | 61 | * **2016/10/11** Add horizontal flip function. 62 | * **2016/10/12** Add Lock function to disable handle stickers. 63 | * **2016/11/30** Added text stickers which supports both text and image background. Thanks to [taoliuh](https://github.com/taoliuh). 64 | * **2016/12/02** Fixed the region of sticker bigger bug,and add more custom configure. 65 | * **2016/12/03** Add more callback 66 | * **2016/12/14** Add [PhotoView](https://github.com/chrisbanes/PhotoView) support. 67 | * **2016/12/15** Add remove methods. 68 | * **2016/12/16** Add Double Tap Callback 69 | * **2016/12/17** Add Constrain Sticker's move area 70 | * **2017/02/07** Custom your icon and icon event 71 | * **2017/04/25** Fix scale err and add more useful function 72 | 73 | ## Todo 74 | - [x] Constrain the sticker's moving area 75 | - [x] Add Double Tap callback 76 | 77 | ## Licence 78 | 79 | ``` 80 | Copyright 2016 wuapnjie 81 | 82 | Licensed under the Apache License, Version 2.0 (the "License"); 83 | you may not use this file except in compliance with the License. 84 | You may obtain a copy of the License at 85 | 86 | http://www.apache.org/licenses/LICENSE-2.0 87 | 88 | Unless required by applicable law or agreed to in writing, software 89 | distributed under the License is distributed on an "AS IS" BASIS, 90 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 91 | See the License for the specific language governing permissions and 92 | limitations under the License. 93 | ``` 94 | 95 | 96 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | defaultConfig { 7 | applicationId "com.xiaopo.flying.stickerview" 8 | minSdkVersion 14 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile "com.android.support:appcompat-v7:$rootProject.ext.supportLibraryVersion" 28 | compile "com.github.chrisbanes:PhotoView:$rootProject.ext.photoViewVersion" 29 | testCompile 'junit:junit:4.12' 30 | compile project(path: ':sticker') 31 | } 32 | -------------------------------------------------------------------------------- /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 /usr/local/android-sdk-linux/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 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/xiaopo/flying/stickerview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.xiaopo.flying.stickerview; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) public class ExampleInstrumentedTest { 18 | @Test public void useAppContext() throws Exception { 19 | // Context of the app under test. 20 | Context appContext = InstrumentationRegistry.getTargetContext(); 21 | 22 | assertEquals("com.xiaopo.flying.stickerview", appContext.getPackageName()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuapnjie/StickerView/4a82f82fba04aacdaffea78c5b63912114b83c7a/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/com/xiaopo/flying/stickerview/HelloIconEvent.java: -------------------------------------------------------------------------------- 1 | package com.xiaopo.flying.stickerview; 2 | 3 | import android.view.MotionEvent; 4 | import android.widget.Toast; 5 | import com.xiaopo.flying.sticker.StickerIconEvent; 6 | import com.xiaopo.flying.sticker.StickerView; 7 | 8 | /** 9 | * @author wupanjie 10 | * @see StickerIconEvent 11 | */ 12 | 13 | public class HelloIconEvent implements StickerIconEvent{ 14 | @Override public void onActionDown(StickerView stickerView, MotionEvent event) { 15 | 16 | } 17 | 18 | @Override public void onActionMove(StickerView stickerView, MotionEvent event) { 19 | 20 | } 21 | 22 | @Override public void onActionUp(StickerView stickerView, MotionEvent event) { 23 | Toast.makeText(stickerView.getContext(), "Hello World!", Toast.LENGTH_SHORT).show(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/xiaopo/flying/stickerview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.xiaopo.flying.stickerview; 2 | 3 | import android.Manifest; 4 | import android.content.pm.PackageManager; 5 | import android.graphics.Color; 6 | import android.graphics.drawable.Drawable; 7 | import android.os.Bundle; 8 | import android.support.annotation.NonNull; 9 | import android.support.v4.app.ActivityCompat; 10 | import android.support.v4.content.ContextCompat; 11 | import android.support.v7.app.AppCompatActivity; 12 | import android.support.v7.widget.Toolbar; 13 | import android.text.Layout; 14 | import android.util.Log; 15 | import android.view.MenuItem; 16 | import android.view.View; 17 | import android.widget.Toast; 18 | 19 | import com.xiaopo.flying.sticker.BitmapStickerIcon; 20 | import com.xiaopo.flying.sticker.DeleteIconEvent; 21 | import com.xiaopo.flying.sticker.DrawableSticker; 22 | import com.xiaopo.flying.sticker.FlipHorizontallyEvent; 23 | import com.xiaopo.flying.sticker.Sticker; 24 | import com.xiaopo.flying.sticker.StickerView; 25 | import com.xiaopo.flying.sticker.TextSticker; 26 | import com.xiaopo.flying.sticker.ZoomIconEvent; 27 | import com.xiaopo.flying.stickerview.util.FileUtil; 28 | 29 | import java.io.File; 30 | import java.util.Arrays; 31 | 32 | public class MainActivity extends AppCompatActivity { 33 | private static final String TAG = MainActivity.class.getSimpleName(); 34 | public static final int PERM_RQST_CODE = 110; 35 | private StickerView stickerView; 36 | private TextSticker sticker; 37 | 38 | @Override 39 | protected void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | setContentView(R.layout.activity_main); 42 | 43 | stickerView = (StickerView) findViewById(R.id.sticker_view); 44 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 45 | 46 | //currently you can config your own icons and icon event 47 | //the event you can custom 48 | BitmapStickerIcon deleteIcon = new BitmapStickerIcon(ContextCompat.getDrawable(this, 49 | com.xiaopo.flying.sticker.R.drawable.sticker_ic_close_white_18dp), 50 | BitmapStickerIcon.LEFT_TOP); 51 | deleteIcon.setIconEvent(new DeleteIconEvent()); 52 | 53 | BitmapStickerIcon zoomIcon = new BitmapStickerIcon(ContextCompat.getDrawable(this, 54 | com.xiaopo.flying.sticker.R.drawable.sticker_ic_scale_white_18dp), 55 | BitmapStickerIcon.RIGHT_BOTOM); 56 | zoomIcon.setIconEvent(new ZoomIconEvent()); 57 | 58 | BitmapStickerIcon flipIcon = new BitmapStickerIcon(ContextCompat.getDrawable(this, 59 | com.xiaopo.flying.sticker.R.drawable.sticker_ic_flip_white_18dp), 60 | BitmapStickerIcon.RIGHT_TOP); 61 | flipIcon.setIconEvent(new FlipHorizontallyEvent()); 62 | 63 | BitmapStickerIcon heartIcon = 64 | new BitmapStickerIcon(ContextCompat.getDrawable(this, R.drawable.ic_favorite_white_24dp), 65 | BitmapStickerIcon.LEFT_BOTTOM); 66 | heartIcon.setIconEvent(new HelloIconEvent()); 67 | 68 | stickerView.setIcons(Arrays.asList(deleteIcon, zoomIcon, flipIcon, heartIcon)); 69 | 70 | //default icon layout 71 | //stickerView.configDefaultIcons(); 72 | 73 | stickerView.setBackgroundColor(Color.WHITE); 74 | stickerView.setLocked(false); 75 | stickerView.setConstrained(true); 76 | 77 | sticker = new TextSticker(this); 78 | 79 | sticker.setDrawable(ContextCompat.getDrawable(getApplicationContext(), 80 | R.drawable.sticker_transparent_background)); 81 | sticker.setText("Hello, world!"); 82 | sticker.setTextColor(Color.BLACK); 83 | sticker.setTextAlign(Layout.Alignment.ALIGN_CENTER); 84 | sticker.resizeText(); 85 | 86 | stickerView.setOnStickerOperationListener(new StickerView.OnStickerOperationListener() { 87 | @Override 88 | public void onStickerAdded(@NonNull Sticker sticker) { 89 | Log.d(TAG, "onStickerAdded"); 90 | } 91 | 92 | @Override 93 | public void onStickerClicked(@NonNull Sticker sticker) { 94 | //stickerView.removeAllSticker(); 95 | if (sticker instanceof TextSticker) { 96 | ((TextSticker) sticker).setTextColor(Color.RED); 97 | stickerView.replace(sticker); 98 | stickerView.invalidate(); 99 | } 100 | Log.d(TAG, "onStickerClicked"); 101 | } 102 | 103 | @Override 104 | public void onStickerDeleted(@NonNull Sticker sticker) { 105 | Log.d(TAG, "onStickerDeleted"); 106 | } 107 | 108 | @Override 109 | public void onStickerDragFinished(@NonNull Sticker sticker) { 110 | Log.d(TAG, "onStickerDragFinished"); 111 | } 112 | 113 | @Override 114 | public void onStickerTouchedDown(@NonNull Sticker sticker) { 115 | Log.d(TAG, "onStickerTouchedDown"); 116 | } 117 | 118 | @Override 119 | public void onStickerZoomFinished(@NonNull Sticker sticker) { 120 | Log.d(TAG, "onStickerZoomFinished"); 121 | } 122 | 123 | @Override 124 | public void onStickerFlipped(@NonNull Sticker sticker) { 125 | Log.d(TAG, "onStickerFlipped"); 126 | } 127 | 128 | @Override 129 | public void onStickerDoubleTapped(@NonNull Sticker sticker) { 130 | Log.d(TAG, "onDoubleTapped: double tap will be with two click"); 131 | } 132 | }); 133 | 134 | if (toolbar != null) { 135 | toolbar.setTitle(R.string.app_name); 136 | toolbar.inflateMenu(R.menu.menu_save); 137 | toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { 138 | @Override 139 | public boolean onMenuItemClick(MenuItem item) { 140 | if (item.getItemId() == R.id.item_save) { 141 | File file = FileUtil.getNewFile(MainActivity.this, "Sticker"); 142 | if (file != null) { 143 | stickerView.save(file); 144 | Toast.makeText(MainActivity.this, "saved in " + file.getAbsolutePath(), 145 | Toast.LENGTH_SHORT).show(); 146 | } else { 147 | Toast.makeText(MainActivity.this, "the file is null", Toast.LENGTH_SHORT).show(); 148 | } 149 | } 150 | // stickerView.replace(new DrawableSticker( 151 | // ContextCompat.getDrawable(MainActivity.this, R.drawable.haizewang_90) 152 | // )); 153 | return false; 154 | } 155 | }); 156 | } 157 | 158 | if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) 159 | != PackageManager.PERMISSION_GRANTED 160 | || ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) 161 | != PackageManager.PERMISSION_GRANTED) { 162 | ActivityCompat.requestPermissions(this, 163 | new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERM_RQST_CODE); 164 | } else { 165 | loadSticker(); 166 | } 167 | } 168 | 169 | private void loadSticker() { 170 | Drawable drawable = 171 | ContextCompat.getDrawable(this, R.drawable.haizewang_215); 172 | Drawable drawable1 = 173 | ContextCompat.getDrawable(this, R.drawable.haizewang_23); 174 | stickerView.addSticker(new DrawableSticker(drawable)); 175 | stickerView.addSticker(new DrawableSticker(drawable1), Sticker.Position.BOTTOM | Sticker.Position.RIGHT); 176 | 177 | Drawable bubble = ContextCompat.getDrawable(this, R.drawable.bubble); 178 | stickerView.addSticker( 179 | new TextSticker(getApplicationContext()) 180 | .setDrawable(bubble) 181 | .setText("Sticker\n") 182 | .setMaxTextSize(14) 183 | .resizeText() 184 | , Sticker.Position.TOP); 185 | } 186 | 187 | @Override 188 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 189 | @NonNull int[] grantResults) { 190 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 191 | if (requestCode == PERM_RQST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 192 | loadSticker(); 193 | } 194 | } 195 | 196 | public void testReplace(View view) { 197 | if (stickerView.replace(sticker)) { 198 | Toast.makeText(MainActivity.this, "Replace Sticker successfully!", Toast.LENGTH_SHORT).show(); 199 | } else { 200 | Toast.makeText(MainActivity.this, "Replace Sticker failed!", Toast.LENGTH_SHORT).show(); 201 | } 202 | } 203 | 204 | public void testLock(View view) { 205 | stickerView.setLocked(!stickerView.isLocked()); 206 | } 207 | 208 | public void testRemove(View view) { 209 | if (stickerView.removeCurrentSticker()) { 210 | Toast.makeText(MainActivity.this, "Remove current Sticker successfully!", Toast.LENGTH_SHORT) 211 | .show(); 212 | } else { 213 | Toast.makeText(MainActivity.this, "Remove current Sticker failed!", Toast.LENGTH_SHORT) 214 | .show(); 215 | } 216 | } 217 | 218 | public void testRemoveAll(View view) { 219 | stickerView.removeAllStickers(); 220 | } 221 | 222 | public void reset(View view) { 223 | stickerView.removeAllStickers(); 224 | loadSticker(); 225 | } 226 | 227 | public void testAdd(View view) { 228 | final TextSticker sticker = new TextSticker(this); 229 | sticker.setText("Hello, world!"); 230 | sticker.setTextColor(Color.BLUE); 231 | sticker.setTextAlign(Layout.Alignment.ALIGN_CENTER); 232 | sticker.resizeText(); 233 | 234 | stickerView.addSticker(sticker); 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /app/src/main/java/com/xiaopo/flying/stickerview/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.xiaopo.flying.stickerview.util; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Environment; 7 | import android.provider.MediaStore; 8 | import android.text.TextUtils; 9 | import android.util.Log; 10 | 11 | import java.io.File; 12 | import java.io.FileInputStream; 13 | import java.io.FileNotFoundException; 14 | import java.io.FileOutputStream; 15 | import java.io.IOException; 16 | import java.nio.channels.FileChannel; 17 | import java.text.SimpleDateFormat; 18 | import java.util.Date; 19 | import java.util.Locale; 20 | 21 | /** 22 | * Created by snowbean on 16-8-5. 23 | */ 24 | public class FileUtil { 25 | private static final String TAG = "FileUtil"; 26 | 27 | public static String getFolderName(String name) { 28 | File mediaStorageDir = 29 | new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), 30 | name); 31 | 32 | if (!mediaStorageDir.exists()) { 33 | if (!mediaStorageDir.mkdirs()) { 34 | return ""; 35 | } 36 | } 37 | return mediaStorageDir.getAbsolutePath(); 38 | } 39 | 40 | /** 41 | * 判断sd卡是否可以用 42 | */ 43 | private static boolean isSDAvailable() { 44 | return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); 45 | } 46 | 47 | public static File getNewFile(Context context, String folderName) { 48 | 49 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA); 50 | 51 | String timeStamp = simpleDateFormat.format(new Date()); 52 | 53 | String path; 54 | if (isSDAvailable()) { 55 | path = getFolderName(folderName) + File.separator + timeStamp + ".jpg"; 56 | } else { 57 | path = context.getFilesDir().getPath() + File.separator + timeStamp + ".jpg"; 58 | } 59 | 60 | if (TextUtils.isEmpty(path)) { 61 | return null; 62 | } 63 | 64 | return new File(path); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_favorite_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuapnjie/StickerView/4a82f82fba04aacdaffea78c5b63912114b83c7a/app/src/main/res/drawable-hdpi/ic_favorite_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_favorite_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuapnjie/StickerView/4a82f82fba04aacdaffea78c5b63912114b83c7a/app/src/main/res/drawable-mdpi/ic_favorite_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuapnjie/StickerView/4a82f82fba04aacdaffea78c5b63912114b83c7a/app/src/main/res/drawable-nodpi/border.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/bubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuapnjie/StickerView/4a82f82fba04aacdaffea78c5b63912114b83c7a/app/src/main/res/drawable-nodpi/bubble.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/haizewang_215.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuapnjie/StickerView/4a82f82fba04aacdaffea78c5b63912114b83c7a/app/src/main/res/drawable-nodpi/haizewang_215.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/haizewang_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuapnjie/StickerView/4a82f82fba04aacdaffea78c5b63912114b83c7a/app/src/main/res/drawable-nodpi/haizewang_23.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/haizewang_90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuapnjie/StickerView/4a82f82fba04aacdaffea78c5b63912114b83c7a/app/src/main/res/drawable-nodpi/haizewang_90.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_favorite_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuapnjie/StickerView/4a82f82fba04aacdaffea78c5b63912114b83c7a/app/src/main/res/drawable-xhdpi/ic_favorite_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_favorite_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuapnjie/StickerView/4a82f82fba04aacdaffea78c5b63912114b83c7a/app/src/main/res/drawable-xxhdpi/ic_favorite_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_favorite_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuapnjie/StickerView/4a82f82fba04aacdaffea78c5b63912114b83c7a/app/src/main/res/drawable-xxxhdpi/ic_favorite_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 20 | 21 | 30 | 31 | 36 | 37 | 43 | 44 | 45 | 46 | 52 | 57 |