├── .gitignore ├── README.md ├── Screenshot_61.jpg ├── Screenshot_62.jpg ├── Screenshot_63.jpg ├── Screenshot_64.jpg ├── app ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── hendyghsta │ │ └── parsinghtml │ │ ├── App.java │ │ ├── common │ │ ├── AppGlide.java │ │ ├── Const.java │ │ ├── mvp │ │ │ ├── BasePresenter.java │ │ │ ├── BaseViewActivity.java │ │ │ ├── BaseViewFragment.java │ │ │ ├── IBasePresenter.java │ │ │ └── IBaseView.java │ │ └── transition │ │ │ ├── BitmapUtil.java │ │ │ ├── Navigator.java │ │ │ └── TransitionHelper.java │ │ ├── data │ │ ├── api │ │ │ ├── Jso.java │ │ │ ├── LinkWeb.java │ │ │ ├── ListResponse.java │ │ │ └── Response.java │ │ └── model │ │ │ └── ListHome.java │ │ ├── services │ │ └── ConnectivityReceiver.java │ │ └── ui │ │ ├── activity │ │ └── MainActivity.java │ │ ├── adapter │ │ ├── HomeAdapter.java │ │ └── MainAdapter.java │ │ └── fragment │ │ └── home │ │ ├── HomeContract.java │ │ ├── HomeFragment.java │ │ └── HomePresenter.java │ └── res │ ├── anim │ ├── scale_down.xml │ ├── scale_up.xml │ └── slide_up.xml │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ ├── activity_main.xml │ ├── fragment_home.xml │ ├── item_home.xml │ └── toolbar_container.xml │ ├── menu │ ├── menu_drawer.xml │ └── menu_home.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches/build_file_checksums.ser 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ParsingHTML 2 | Parsing HTML with Android Studio 3 | 4 | menggunakan 5 | Architecture base MVP 6 | 7 | # Root 8 | ![](https://github.com/hendyghsta/ParsingHTML/blob/master/Screenshot_61.jpg) 9 | 10 | ![](https://github.com/hendyghsta/ParsingHTML/blob/master/Screenshot_63.jpg) 11 | 12 | # List 13 | ![](https://github.com/hendyghsta/ParsingHTML/blob/master/Screenshot_62.jpg) 14 | 15 | ![](https://github.com/hendyghsta/ParsingHTML/blob/master/Screenshot_64.jpg) 16 | -------------------------------------------------------------------------------- /Screenshot_61.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/Screenshot_61.jpg -------------------------------------------------------------------------------- /Screenshot_62.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/Screenshot_62.jpg -------------------------------------------------------------------------------- /Screenshot_63.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/Screenshot_63.jpg -------------------------------------------------------------------------------- /Screenshot_64.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/Screenshot_64.jpg -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | defaultConfig { 6 | applicationId "com.hendyghsta.parsinghtml" 7 | minSdkVersion 21 8 | targetSdkVersion 27 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | compileOptions { 20 | targetCompatibility JavaVersion.VERSION_1_8 21 | sourceCompatibility JavaVersion.VERSION_1_8 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: 'libs', include: ['*.jar']) 27 | testImplementation 'junit:junit:4.12' 28 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 29 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 30 | implementation 'com.android.support:appcompat-v7:27.1.1' 31 | implementation 'com.android.support:support-v13:27.1.1' 32 | implementation 'com.android.support:support-v4:27.1.1' 33 | implementation 'com.android.support:design:27.1.1' 34 | implementation 'com.android.support:exifinterface:27.1.1' 35 | implementation 'com.android.support:cardview-v7:27.1.1' 36 | implementation 'com.android.support:palette-v7:27.1.1' 37 | implementation 'io.reactivex.rxjava2:rxjava:2.1.16' 38 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' 39 | implementation 'org.jsoup:jsoup:1.11.3' 40 | implementation 'com.github.florent37:retrojsoup:1.0.4' 41 | implementation 'com.github.florent37:rxjsoup:1.0.4' 42 | implementation 'org.glassfish:javax.annotation:10.0-b28' 43 | implementation 'com.jakewharton:butterknife:8.8.1' 44 | implementation 'com.github.bumptech.glide:glide:4.7.1' 45 | implementation 'com.afollestad.material-dialogs:core:0.9.6.0' 46 | implementation 'com.afollestad.material-dialogs:commons:0.9.6.0' 47 | implementation 'com.balysv.materialmenu:material-menu:2.0.0' 48 | implementation 'com.github.omadahealth:swipy:1.2.3@aar' 49 | implementation 'com.karumi:dexter:5.0.0' 50 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' 51 | annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1' 52 | annotationProcessor 'com.github.florent37:retrojsoup-compiler:1.0.4' 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/App.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml; 2 | 3 | import android.app.Application; 4 | 5 | import com.hendyghsta.parsinghtml.services.ConnectivityReceiver; 6 | 7 | /** 8 | * Created by hendyghsta on 30/09/2018. 9 | */ 10 | public class App extends Application { 11 | private static final String TAG = App.class.getSimpleName(); 12 | private static App mInstance; 13 | 14 | public static synchronized App getInstance(){ 15 | return mInstance; 16 | } 17 | 18 | @Override 19 | public void onCreate() { 20 | super.onCreate(); 21 | mInstance = this; 22 | } 23 | 24 | public void setConnectivityListener(ConnectivityReceiver.ConnectivityReceiverListener listener) { 25 | ConnectivityReceiver.connectivityReceiverListener = listener; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/common/AppGlide.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.common; 2 | 3 | import com.bumptech.glide.annotation.GlideModule; 4 | import com.bumptech.glide.module.AppGlideModule; 5 | 6 | /** 7 | * Created by hendyghsta on 07/16/2018. 8 | */ 9 | @GlideModule 10 | public class AppGlide extends AppGlideModule { 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/common/Const.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.common; 2 | 3 | import android.content.Context; 4 | import android.os.Environment; 5 | import android.support.annotation.IntDef; 6 | import android.support.annotation.NonNull; 7 | import android.util.Base64; 8 | 9 | import com.hendyghsta.parsinghtml.R; 10 | 11 | import java.io.File; 12 | import java.io.UnsupportedEncodingException; 13 | import java.lang.annotation.Retention; 14 | import java.lang.annotation.RetentionPolicy; 15 | 16 | /** 17 | * Created by hendyghsta on 08/14/2018. 18 | */ 19 | public class Const { 20 | 21 | public static final String FRAGMENT_RES_ID = "fragment_resource_id"; 22 | public static final String DETAIL_ELEMENT = "detail_element"; 23 | public static final String BITMAP_ID = "bitmap_id"; 24 | public static final String FROM_LAYOUT = "from_layout"; 25 | public static final String PARCEL = "parcel"; 26 | public static final String ITEM_TEXT = "item_text"; 27 | public static final String ID = "id"; 28 | public static final String FOLDER_FILE = "folder_file"; 29 | public static final int ITEM_VIEW_TYPE = 0; 30 | public static final String URL = "https://bioskop45.com"; 31 | public static final int BANNER_AD_VIEW_TYPE = 1; 32 | 33 | public static File getParentFile(@NonNull Context context) { 34 | String state = Environment.getExternalStorageState(); 35 | if (Environment.MEDIA_MOUNTED.equals(state)) { 36 | File file = new File(Environment.getExternalStoragePublicDirectory(context.getResources().getString(R.string.app_name)), "download"); 37 | if (!file.isDirectory()){ 38 | file.mkdirs(); 39 | } 40 | return file; 41 | } else { 42 | return context.getCacheDir(); 43 | } 44 | } 45 | 46 | @IntDef({ViewType.ANIME, ViewType.TOKUKATSU}) 47 | @Retention(RetentionPolicy.SOURCE) 48 | public @interface ViewType { 49 | int ANIME = 100; 50 | int TOKUKATSU = 200; 51 | } 52 | 53 | public static String decodeString(String str) { 54 | byte[] decode = Base64.decode(str, 0); 55 | String str2 = ""; 56 | try { 57 | return new String(decode, "UTF-8"); 58 | } catch (UnsupportedEncodingException e) { 59 | e.printStackTrace(); 60 | return str2; 61 | } catch (Throwable th) { 62 | return str2; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/common/mvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.common.mvp; 2 | 3 | 4 | /** 5 | * Abstract base class to be extended by any MVP Presenter. It contains common attributes and 6 | * methods to be shared across Presenters. 7 | * 8 | * @param a generic type to indicate a type of MVP View 9 | */ 10 | public class BasePresenter implements IBasePresenter { 11 | 12 | protected ViewT view; 13 | 14 | @Override 15 | public void onViewActive(ViewT view) { 16 | this.view = view; 17 | } 18 | 19 | @Override 20 | public void onViewInactive() { 21 | view = null; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/common/mvp/BaseViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.common.mvp; 2 | 3 | import android.app.Activity; 4 | import android.app.ProgressDialog; 5 | import android.content.DialogInterface; 6 | import android.os.Bundle; 7 | import android.os.PersistableBundle; 8 | import android.support.annotation.Nullable; 9 | import android.support.design.widget.Snackbar; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.widget.Toast; 12 | 13 | import com.afollestad.materialdialogs.MaterialDialog; 14 | 15 | /** 16 | * Created by hendyghsta on 12/09/2017. 17 | */ 18 | 19 | public abstract class BaseViewActivity extends AppCompatActivity implements IBaseView { 20 | 21 | private ProgressDialog dialog; 22 | 23 | @Override 24 | public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) { 25 | super.onCreate(savedInstanceState, persistentState); 26 | dialog = new ProgressDialog(this); 27 | } 28 | 29 | @Override 30 | public void showToastMessage(String message) { 31 | Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); 32 | } 33 | 34 | @Override 35 | public void showProgressDialog(boolean show) { 36 | dialog.setMessage("Loading..."); 37 | if (show) 38 | dialog.show(); 39 | else 40 | dialog.dismiss(); 41 | } 42 | 43 | @Override 44 | public Activity getActivity() { 45 | return this; 46 | } 47 | 48 | @Override 49 | public void showDialog(String title, String content, DialogInterface.OnCancelListener listener) { 50 | new MaterialDialog.Builder(this) 51 | .title(title) 52 | .content(content) 53 | .cancelListener(listener).show(); 54 | } 55 | 56 | @Override 57 | public void showSnackBar(String msg, int duration) { 58 | Snackbar.make(findViewById(android.R.id.content),msg,duration); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/common/mvp/BaseViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.common.mvp; 2 | 3 | import android.app.Fragment; 4 | import android.app.ProgressDialog; 5 | import android.content.DialogInterface; 6 | import android.os.Bundle; 7 | import android.support.annotation.Nullable; 8 | import android.support.design.widget.Snackbar; 9 | import android.widget.Toast; 10 | 11 | import com.afollestad.materialdialogs.MaterialDialog; 12 | 13 | public abstract class BaseViewFragment extends Fragment implements IBaseView { 14 | 15 | private ProgressDialog dialog; 16 | 17 | @Override 18 | public void onCreate(@Nullable Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | dialog = new ProgressDialog(getActivity()); 21 | } 22 | 23 | @Override 24 | public void showToastMessage(String message) { 25 | Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show(); 26 | } 27 | 28 | @Override 29 | public void showProgressDialog(boolean show) { 30 | dialog.setMessage("Loading..."); 31 | if (show) 32 | dialog.show(); 33 | else 34 | dialog.dismiss(); 35 | } 36 | 37 | @Override 38 | public void showDialog(String title, String content, DialogInterface.OnCancelListener listener) { 39 | new MaterialDialog.Builder(getActivity()) 40 | .title(title) 41 | .content(content) 42 | .cancelListener(listener).show(); 43 | } 44 | 45 | @Override 46 | public void showSnackBar(String msg,int duration) { 47 | Snackbar.make(getActivity().findViewById(android.R.id.content),msg,Snackbar.LENGTH_LONG); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/common/mvp/IBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.common.mvp; 2 | 3 | 4 | public interface IBasePresenter { 5 | 6 | void onViewActive(ViewT view); 7 | 8 | void onViewInactive(); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/common/mvp/IBaseView.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.common.mvp; 2 | 3 | 4 | import android.app.Activity; 5 | import android.content.DialogInterface; 6 | import android.support.annotation.Nullable; 7 | 8 | 9 | public interface IBaseView { 10 | 11 | void showToastMessage(String message); 12 | 13 | void showProgressDialog(boolean show); 14 | 15 | Activity getActivity(); 16 | 17 | void showDialog(String title, String content, @Nullable DialogInterface.OnCancelListener listener); 18 | 19 | void showSnackBar(String msg, int duration); 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/common/transition/BitmapUtil.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.common.transition; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Canvas; 6 | import android.util.LruCache; 7 | import android.view.View; 8 | 9 | import com.hendyghsta.parsinghtml.common.Const; 10 | 11 | import java.util.UUID; 12 | 13 | 14 | public class BitmapUtil { 15 | private static LruCache mMemoryCache; 16 | static { 17 | final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); 18 | final int cacheSize = maxMemory / 8; // Use 1/8th of the available memory for this memory cache. 19 | mMemoryCache = new LruCache(cacheSize) { 20 | @Override 21 | protected int sizeOf(String key, Bitmap bitmap) { 22 | return bitmap.getByteCount() / 1024; // The cache size will be measured in kilobytes rather than number of items. 23 | } 24 | }; 25 | } 26 | 27 | public static void storeBitmapInIntent(Bitmap bitmap, Intent intent) { 28 | String key = "bitmap_" + UUID.randomUUID(); 29 | storeBitmapInMemCache(key, bitmap); 30 | intent.putExtra(Const.BITMAP_ID, key); 31 | 32 | // ByteArrayOutputStream bs = new ByteArrayOutputStream(); 33 | // bitmap.compress(Bitmap.CompressFormat.PNG, 0, bs); 34 | // intent.putExtra("background", bs.toByteArray()); 35 | } 36 | 37 | public static void storeBitmapInMemCache(String key, Bitmap bitmap) { 38 | if (getBitmapFromMemCache(key) == null) { 39 | mMemoryCache.put(key, bitmap); 40 | } 41 | } 42 | 43 | public static Bitmap getBitmapFromMemCache(String key) { 44 | return mMemoryCache.get(key); 45 | } 46 | 47 | public static Bitmap fetchBitmapFromIntent(Intent intent) { 48 | String key = intent.getStringExtra(Const.BITMAP_ID); 49 | // byte[] byteArray = intent.getByteArrayExtra("background"); 50 | // Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); 51 | return getBitmapFromMemCache(key); 52 | } 53 | 54 | public static Bitmap createBitmap(View v) { 55 | Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888); 56 | Canvas canvas = new Canvas(bitmap); 57 | v.draw(canvas); 58 | return bitmap; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/common/transition/Navigator.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.common.transition; 2 | 3 | 4 | import android.content.Intent; 5 | import android.support.v4.app.ActivityCompat; 6 | import android.support.v4.app.ActivityOptionsCompat; 7 | import android.support.v4.util.Pair; 8 | import android.support.v4.view.ViewCompat; 9 | import android.view.View; 10 | 11 | import com.hendyghsta.parsinghtml.R; 12 | import com.hendyghsta.parsinghtml.common.Const; 13 | import com.hendyghsta.parsinghtml.ui.activity.MainActivity; 14 | 15 | public class Navigator { 16 | 17 | public static int ANIM_DURATION = 350; 18 | 19 | 20 | public static void launchDetailHome(MainActivity fromActivity, String id, View fromView, View backgroundView, int layout) { 21 | ViewCompat.setTransitionName(fromView, Const.DETAIL_ELEMENT); 22 | ActivityOptionsCompat options = 23 | TransitionHelper.makeOptionsCompat( 24 | fromActivity, 25 | Pair.create(fromView, Const.DETAIL_ELEMENT) 26 | ); 27 | Intent intent = new Intent(fromActivity, MainActivity.class); 28 | intent.putExtra(Const.FRAGMENT_RES_ID, layout); 29 | intent.putExtra(Const.ID,id); 30 | if (backgroundView != null) 31 | BitmapUtil.storeBitmapInIntent(BitmapUtil.createBitmap(backgroundView), intent); 32 | ActivityCompat.startActivity(fromActivity, intent, options.toBundle()); 33 | fromActivity.overridePendingTransition(R.anim.slide_up, R.anim.scale_down); 34 | } 35 | 36 | public static void launchHome(MainActivity fromActivity, View fromView, View backgroundView, int layout) { 37 | ViewCompat.setTransitionName(fromView, Const.DETAIL_ELEMENT); 38 | ActivityOptionsCompat options = 39 | TransitionHelper.makeOptionsCompat( 40 | fromActivity, 41 | Pair.create(fromView, Const.DETAIL_ELEMENT) 42 | ); 43 | Intent intent = new Intent(fromActivity, MainActivity.class); 44 | intent.putExtra(Const.FRAGMENT_RES_ID, layout); 45 | intent.putExtra(Const.FROM_LAYOUT,true); 46 | if (backgroundView != null) BitmapUtil.storeBitmapInIntent(BitmapUtil.createBitmap(backgroundView), intent); 47 | ActivityCompat.startActivity(fromActivity, intent, options.toBundle()); 48 | fromActivity.overridePendingTransition(R.anim.slide_up, R.anim.scale_down); 49 | } 50 | 51 | public static void launchFragment(MainActivity fromActivity, String costum, int layout){ 52 | ActivityOptionsCompat options = 53 | TransitionHelper.makeOptionsCompat( 54 | fromActivity 55 | ); 56 | Intent intent = new Intent(fromActivity, MainActivity.class); 57 | intent.putExtra(Const.ID, costum); 58 | intent.putExtra(Const.FRAGMENT_RES_ID, layout); 59 | ActivityCompat.startActivity(fromActivity, intent, options.toBundle()); 60 | fromActivity.overridePendingTransition(R.anim.slide_up, R.anim.scale_down); 61 | } 62 | 63 | public static void launchSimpleIdHome(MainActivity fromActivity,String id, View backgroundView, int layout) { 64 | ActivityOptionsCompat options = 65 | TransitionHelper.makeOptionsCompat( 66 | fromActivity 67 | ); 68 | Intent intent = new Intent(fromActivity, MainActivity.class); 69 | intent.putExtra(Const.FRAGMENT_RES_ID, layout); 70 | intent.putExtra(Const.ID,id); 71 | if (backgroundView != null) BitmapUtil.storeBitmapInIntent(BitmapUtil.createBitmap(backgroundView), intent); 72 | ActivityCompat.startActivity(fromActivity, intent, options.toBundle()); 73 | fromActivity.overridePendingTransition(R.anim.slide_up, R.anim.scale_down); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/common/transition/TransitionHelper.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.common.transition; 2 | 3 | import android.animation.Animator; 4 | import android.app.Activity; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.support.v4.app.ActivityCompat; 8 | import android.support.v4.app.ActivityOptionsCompat; 9 | import android.support.v4.util.Pair; 10 | import android.transition.Transition; 11 | import android.view.View; 12 | import android.view.ViewTreeObserver; 13 | import android.view.Window; 14 | 15 | import com.hendyghsta.parsinghtml.common.mvp.BaseViewActivity; 16 | import com.hendyghsta.parsinghtml.common.mvp.BaseViewFragment; 17 | import com.hendyghsta.parsinghtml.services.ConnectivityReceiver; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | import java.util.ListIterator; 23 | 24 | /** 25 | * Provides extra lifecycle events and shims for shared element transitions 26 | * See the included MainActivity and BaseFragment for example use 27 | */ 28 | public class TransitionHelper { 29 | 30 | Activity activity; 31 | 32 | private TransitionHelper(Activity activity, Bundle savedInstanceState) { 33 | this.activity = activity; 34 | isAfterEnter = savedInstanceState != null; //if saved instance is not null we've already "entered" 35 | postponeEnterTransition(); //we postpone to prevent status and nav bars from flashing during shared element transitions 36 | } 37 | 38 | /** 39 | * Should be called from Activity.onResume() 40 | */ 41 | public void onResume() { 42 | if (isAfterEnter) return; 43 | 44 | if (!isViewCreatedAlreadyCalled) onViewCreated(); 45 | 46 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 47 | onAfterEnter(); 48 | } else { 49 | activity.getWindow().getSharedElementEnterTransition().addListener(new Transition.TransitionListener() { 50 | @Override 51 | public void onTransitionStart(Transition transition) { 52 | if (isAfterEnter()) for (Listener listener : listeners) listener.onBeforeReturn(); 53 | } 54 | 55 | @Override 56 | public void onTransitionEnd(Transition transition) { 57 | if (!isAfterEnter()) onAfterEnter(); 58 | } 59 | 60 | @Override 61 | public void onTransitionCancel(Transition transition) { 62 | if (!isAfterEnter()) onAfterEnter(); 63 | } 64 | 65 | @Override 66 | public void onTransitionPause(Transition transition) { 67 | } 68 | 69 | @Override 70 | public void onTransitionResume(Transition transition) { 71 | } 72 | }); 73 | } 74 | } 75 | 76 | /** 77 | * Should be called from Activity.onBackPressed() 78 | */ 79 | public void onBackPressed() { 80 | boolean isConsumed = false; 81 | for (Listener listener : listeners) { 82 | isConsumed = listener.onBeforeBack() || isConsumed; 83 | } 84 | if (!isConsumed) ActivityCompat.finishAfterTransition(activity); 85 | } 86 | 87 | /** 88 | * Should be called immediately after all shared transition views are inflated. 89 | * If using fragments, recommend calling at the beginning of Fragment.onViewCreated(). 90 | */ 91 | private boolean isViewCreatedAlreadyCalled = false; 92 | public void onViewCreated() { 93 | if (isViewCreatedAlreadyCalled) return; 94 | isViewCreatedAlreadyCalled = true; 95 | 96 | View contentView = activity.getWindow().getDecorView().findViewById(android.R.id.content); 97 | for (Listener listener : listeners) listener.onBeforeViewShows(contentView); 98 | if (!isAfterEnter()) { for (Listener listener : listeners) listener.onBeforeEnter(contentView); } 99 | 100 | if (isPostponeEnterTransition) startPostponedEnterTransition(); 101 | } 102 | 103 | /** 104 | * Call from Activity.onSaveInstanceState() 105 | * @param outState 106 | */ 107 | public void onSaveInstanceState(Bundle outState) { 108 | outState.putBoolean("isAfterEnter", isAfterEnter); 109 | } 110 | 111 | /** 112 | * A parent object that owns an instance of TransitionHelper 113 | * Your Activity should implement Source and call TransitionHelper.init() from Activity.onCreate() 114 | */ 115 | public interface Source { 116 | /** 117 | * Getter for TransitionHelper instance 118 | * @return 119 | */ 120 | TransitionHelper getTransitionHelper(); 121 | 122 | /** 123 | * Setter for TransitionHelper instance 124 | * @param transitionHelper 125 | */ 126 | void setTransitionHelper(TransitionHelper transitionHelper); 127 | } 128 | 129 | 130 | 131 | /** 132 | * Listens for extra transition events 133 | * Activities, Fragments, and other views should implement Listener and call TransitionHelper.of(...).addListener(this) 134 | */ 135 | public interface Listener { 136 | /** 137 | * Called during every onViewCreated 138 | * @param contentView 139 | */ 140 | void onBeforeViewShows(View contentView); 141 | 142 | /** 143 | * Called during onViewCreated only on an enter transition 144 | * @param contentView 145 | */ 146 | void onBeforeEnter(View contentView); 147 | 148 | /** 149 | * Called after enter transition is finished for L+, otherwise called immediately during first onResume 150 | */ 151 | void onAfterEnter(); 152 | 153 | 154 | /** 155 | * Called during Activity.onBackPressed() 156 | * @return true if the listener has consumed the event, false otherwise 157 | */ 158 | boolean onBeforeBack(); 159 | 160 | void onBeforeReturn(); 161 | } 162 | 163 | private List listeners = new ArrayList<>(); 164 | public void addListener(Listener listener) { 165 | listeners.add(listener); 166 | } 167 | 168 | private void onAfterEnter() { 169 | for (Listener listener : listeners) listener.onAfterEnter(); 170 | isAfterEnter = true; 171 | } 172 | 173 | private boolean isAfterEnter = false; 174 | public boolean isAfterEnter() { return isAfterEnter; } 175 | 176 | private boolean isPostponeEnterTransition = false; 177 | private void postponeEnterTransition() { 178 | if (isAfterEnter) return; 179 | ActivityCompat.postponeEnterTransition(activity); 180 | isPostponeEnterTransition = true; 181 | } 182 | 183 | 184 | private void startPostponedEnterTransition() { 185 | final View decor = activity.getWindow().getDecorView(); 186 | decor.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 187 | @Override 188 | public boolean onPreDraw() { 189 | decor.getViewTreeObserver().removeOnPreDrawListener(this); 190 | ActivityCompat.startPostponedEnterTransition(activity); 191 | return true; 192 | } 193 | }); 194 | } 195 | 196 | public static void excludeEnterTarget(Activity activity, int targetId, boolean exclude) { 197 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 198 | activity.getWindow().getEnterTransition().excludeTarget(targetId, exclude); 199 | } 200 | } 201 | 202 | 203 | //STATICS: 204 | /** 205 | * Get the TransitionHelper object for an Activity 206 | * @param a 207 | * @return 208 | */ 209 | public static TransitionHelper of(Activity a) { 210 | return ((Source) a).getTransitionHelper(); 211 | } 212 | 213 | /** 214 | * Initialize the TransitionHelper object. Should be called at the beginning of Activity.onCreate() 215 | * @param source 216 | * @param savedInstanceState 217 | */ 218 | public static void init(Source source, Bundle savedInstanceState) { 219 | source.setTransitionHelper(new TransitionHelper((Activity) source, savedInstanceState)); 220 | } 221 | 222 | public static ActivityOptionsCompat makeOptionsCompat(Activity fromActivity, Pair... sharedElements) { 223 | ArrayList> list = new ArrayList<>(Arrays.asList(sharedElements)); 224 | 225 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 226 | list.add(Pair.create(fromActivity.findViewById(android.R.id.statusBarBackground), Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME)); 227 | list.add(Pair.create(fromActivity.findViewById(android.R.id.navigationBarBackground), Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME)); 228 | } 229 | 230 | //remove any views that are null 231 | for (ListIterator> iter = list.listIterator(); iter.hasNext();) { 232 | Pair pair = iter.next(); 233 | if (pair.first == null) iter.remove(); 234 | } 235 | 236 | sharedElements = list.toArray(new Pair[list.size()]); 237 | return ActivityOptionsCompat.makeSceneTransitionAnimation( 238 | fromActivity, 239 | sharedElements 240 | ); 241 | } 242 | 243 | public static void fadeThenFinish(View v, final Activity a) { 244 | if (v != null) { 245 | v.animate() //fade out the view before finishing the activity (for cleaner L transition) 246 | .alpha(0) 247 | .setDuration(100) 248 | .setListener( 249 | new Animator.AnimatorListener() { 250 | @Override 251 | public void onAnimationStart(Animator animation) { 252 | 253 | } 254 | 255 | @Override 256 | public void onAnimationEnd(Animator animation) { 257 | ActivityCompat.finishAfterTransition(a); 258 | } 259 | 260 | @Override 261 | public void onAnimationCancel(Animator animation) { 262 | 263 | } 264 | 265 | @Override 266 | public void onAnimationRepeat(Animator animation) { 267 | 268 | } 269 | } 270 | ) 271 | .start(); 272 | } 273 | } 274 | 275 | public static class BaseActivity extends BaseViewActivity implements Source, Listener, ConnectivityReceiver.ConnectivityReceiverListener { 276 | TransitionHelper transitionHelper; 277 | 278 | @Override 279 | public TransitionHelper getTransitionHelper() { 280 | return transitionHelper; 281 | } 282 | 283 | @Override 284 | public void setTransitionHelper(TransitionHelper transitionHelper) { 285 | this.transitionHelper = transitionHelper; 286 | } 287 | 288 | @Override 289 | protected void onCreate(Bundle savedInstanceState) { 290 | TransitionHelper.init(this, savedInstanceState); 291 | TransitionHelper.of(this).addListener(this); 292 | 293 | super.onCreate(savedInstanceState); 294 | } 295 | 296 | @Override 297 | public void onSaveInstanceState(Bundle outState) { 298 | TransitionHelper.of(this).onSaveInstanceState(outState); 299 | super.onSaveInstanceState(outState); 300 | } 301 | 302 | @Override 303 | protected void onResume() { 304 | TransitionHelper.of(this).onResume(); 305 | super.onResume(); 306 | } 307 | 308 | @Override 309 | public void onBackPressed() { 310 | TransitionHelper.of(this).onBackPressed(); 311 | } 312 | 313 | 314 | @Override 315 | public void onBeforeViewShows(View contentView) { 316 | 317 | } 318 | 319 | @Override 320 | public void onBeforeEnter(View contentView) { 321 | 322 | } 323 | 324 | @Override 325 | public void onAfterEnter() { 326 | 327 | } 328 | 329 | @Override 330 | public boolean onBeforeBack() { 331 | return false; 332 | } 333 | 334 | @Override 335 | public void onBeforeReturn() { 336 | 337 | } 338 | 339 | @Override 340 | public Activity getActivity() { 341 | return this; 342 | } 343 | 344 | @Override 345 | public void onNetworkConnectionChanged(boolean isConnected) { 346 | 347 | } 348 | } 349 | 350 | public static class BaseFragment extends BaseViewFragment implements Listener, ConnectivityReceiver.ConnectivityReceiverListener { 351 | 352 | @Override 353 | public void onCreate(Bundle savedInstanceState) { 354 | TransitionHelper.of(getActivity()).addListener(this); 355 | super.onCreate(savedInstanceState); 356 | 357 | } 358 | 359 | @Override 360 | public void onViewCreated(View view, Bundle savedInstanceState) { 361 | TransitionHelper.of(getActivity()).onViewCreated(); 362 | super.onViewCreated(view, savedInstanceState); 363 | } 364 | 365 | @Override 366 | public void onBeforeViewShows(View contentView) { 367 | 368 | } 369 | 370 | @Override 371 | public void onBeforeEnter(View contentView) { 372 | 373 | } 374 | 375 | @Override 376 | public void onAfterEnter() { 377 | 378 | } 379 | 380 | @Override 381 | public boolean onBeforeBack() { 382 | return false; 383 | } 384 | 385 | @Override 386 | public void onBeforeReturn() { 387 | 388 | } 389 | 390 | @Override 391 | public void onNetworkConnectionChanged(boolean isConnected) { 392 | 393 | } 394 | } 395 | 396 | 397 | } 398 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/data/api/Jso.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.data.api; 2 | 3 | import com.github.florent37.retrojsoup.RetroJsoup; 4 | 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import okhttp3.OkHttpClient; 8 | 9 | /** 10 | * Created by hendyghsta on 08/14/2018. 11 | */ 12 | public class Jso { 13 | private static OkHttpClient getClient(){ 14 | OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder() 15 | .connectTimeout(15, TimeUnit.SECONDS) 16 | .readTimeout(30,TimeUnit.SECONDS) 17 | .writeTimeout(15, TimeUnit.SECONDS); 18 | httpBuilder.interceptors().add(chain -> chain.proceed(chain.request())); 19 | return httpBuilder.build(); 20 | } 21 | 22 | 23 | public static LinkWeb web(String url){ 24 | RetroJsoup jsoup = new RetroJsoup.Builder() 25 | .url(url) 26 | .client(getClient()) 27 | .build(); 28 | return jsoup.create(LinkWeb.class); 29 | } 30 | 31 | 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/data/api/LinkWeb.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.data.api; 2 | 3 | import com.github.florent37.retrojsoup.annotations.Select; 4 | import com.hendyghsta.parsinghtml.data.model.ListHome; 5 | 6 | import io.reactivex.Observable; 7 | 8 | 9 | /** 10 | * Created by hendyghsta on 08/14/2018. 11 | */ 12 | public interface LinkWeb { 13 | 14 | @Select("#wrap #content .filmborder .filmcontent") 15 | Observable homeLastest(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/data/api/ListResponse.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.data.api; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.widget.Toast; 6 | 7 | import java.util.List; 8 | 9 | import io.reactivex.observers.DisposableSingleObserver; 10 | 11 | /** 12 | * Created by hendyghsta on 23/09/2018. 13 | */ 14 | public class ListResponse extends DisposableSingleObserver>{ 15 | 16 | private Context context; 17 | 18 | public ListResponse(Context context) { 19 | this.context = context; 20 | } 21 | 22 | @Override 23 | public void onSuccess(List list) { 24 | 25 | } 26 | 27 | @Override 28 | public void onError(Throwable e) { 29 | Log.e("Response",e.toString()); 30 | Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/data/api/Response.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.data.api; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.widget.Toast; 6 | 7 | import io.reactivex.observers.DisposableObserver; 8 | 9 | /** 10 | * Created by hendyghsta on 22/09/2018. 11 | */ 12 | public class Response extends DisposableObserver { 13 | 14 | private Context context; 15 | 16 | public Response(Context context) { 17 | this.context = context; 18 | } 19 | 20 | @Override 21 | public void onNext(T t) { 22 | 23 | } 24 | 25 | @Override 26 | public void onError(Throwable e) { 27 | Log.e("Response",e.toString()); 28 | Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show(); 29 | } 30 | 31 | @Override 32 | public void onComplete() { 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/data/model/ListHome.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.data.model; 2 | 3 | import com.github.florent37.retrojsoup.annotations.JsoupHref; 4 | import com.github.florent37.retrojsoup.annotations.JsoupSrc; 5 | import com.github.florent37.retrojsoup.annotations.JsoupText; 6 | 7 | /** 8 | * Created by hendyghsta on 30/09/2018. 9 | */ 10 | public class ListHome { 11 | 12 | @JsoupText(".moviefilm .movief h2 a") 13 | public String title; 14 | 15 | @JsoupText(".moviefilm .quality span") 16 | public String quality; 17 | 18 | @JsoupSrc(".moviefilm a img") 19 | public String thumbnail; 20 | 21 | @JsoupHref(".moviefilm a") 22 | public String url; 23 | 24 | @Override 25 | public String toString() { 26 | return title+",\n"+ 27 | quality+",\n"+ 28 | thumbnail+",\n"+ 29 | url; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/services/ConnectivityReceiver.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.services; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.ConnectivityManager; 7 | import android.net.NetworkInfo; 8 | 9 | import com.hendyghsta.parsinghtml.App; 10 | 11 | 12 | /** 13 | * Created by hendyghsta on 08/14/2018. 14 | */ 15 | public class ConnectivityReceiver extends BroadcastReceiver { 16 | public static ConnectivityReceiverListener connectivityReceiverListener; 17 | 18 | public ConnectivityReceiver() { 19 | super(); 20 | } 21 | 22 | @Override 23 | public void onReceive(Context context, Intent intent) { 24 | ConnectivityManager cm = (ConnectivityManager) context 25 | .getSystemService(Context.CONNECTIVITY_SERVICE); 26 | NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); 27 | boolean isConnected = activeNetwork != null 28 | && activeNetwork.isConnectedOrConnecting(); 29 | 30 | if (connectivityReceiverListener != null) { 31 | connectivityReceiverListener.onNetworkConnectionChanged(isConnected); 32 | } 33 | } 34 | 35 | public static boolean isConnected() { 36 | ConnectivityManager cm = (ConnectivityManager) App.getInstance().getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); 37 | NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); 38 | return activeNetwork != null 39 | && activeNetwork.isConnectedOrConnecting(); 40 | } 41 | 42 | public interface ConnectivityReceiverListener { 43 | void onNetworkConnectionChanged(boolean isConnected); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/ui/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.ui.activity; 2 | 3 | import android.app.Activity; 4 | import android.app.Fragment; 5 | import android.app.FragmentTransaction; 6 | import android.graphics.drawable.BitmapDrawable; 7 | import android.os.Bundle; 8 | import android.support.annotation.NonNull; 9 | import android.support.design.widget.NavigationView; 10 | import android.support.design.widget.Snackbar; 11 | import android.support.v4.app.ActivityCompat; 12 | import android.support.v4.view.GravityCompat; 13 | import android.support.v4.widget.DrawerLayout; 14 | import android.support.v7.widget.Toolbar; 15 | import android.view.MenuItem; 16 | import android.view.View; 17 | 18 | import com.balysv.materialmenu.MaterialMenuDrawable; 19 | import com.balysv.materialmenu.MaterialMenuView; 20 | import com.hendyghsta.parsinghtml.R; 21 | import com.hendyghsta.parsinghtml.common.Const; 22 | import com.hendyghsta.parsinghtml.common.transition.BitmapUtil; 23 | import com.hendyghsta.parsinghtml.common.transition.TransitionHelper; 24 | import com.hendyghsta.parsinghtml.ui.fragment.home.HomeFragment; 25 | 26 | import butterknife.BindView; 27 | import butterknife.ButterKnife; 28 | 29 | public class MainActivity extends TransitionHelper.BaseActivity implements 30 | NavigationView.OnNavigationItemSelectedListener{ 31 | 32 | @BindView(R.id.toolbar) Toolbar toolbar; 33 | @BindView(R.id.material_menu_button) MaterialMenuView homeButton; 34 | @BindView(R.id.nav_view) NavigationView navigationView; 35 | public @BindView(R.id.drawerLayout) DrawerLayout drawerLayout; 36 | public @BindView(R.id.base_fragment_background) View fragmentBackround; 37 | protected static String BASE_FRAGMENT = "base_fragment"; 38 | private MaterialMenuDrawable.IconState currentIconState; 39 | 40 | @Override 41 | protected void onCreate(Bundle savedInstanceState) { 42 | super.onCreate(savedInstanceState); 43 | setContentView(R.layout.activity_main); 44 | ButterKnife.bind(this); 45 | initToolbar(); 46 | initBaseFragment(savedInstanceState); 47 | initNavigation(); 48 | } 49 | 50 | private void initToolbar() { 51 | if (toolbar != null) { 52 | setSupportActionBar(toolbar); 53 | getSupportActionBar().setDisplayHomeAsUpEnabled(false); 54 | getSupportActionBar().setTitle(""); 55 | homeButton.setOnClickListener(v -> { 56 | if (homeButton.getIconState() != MaterialMenuDrawable.IconState.BURGER) 57 | onBackPressed(); 58 | else 59 | drawerLayout.openDrawer(GravityCompat.START); 60 | }); 61 | } 62 | } 63 | 64 | private void initNavigation() { 65 | navigationView.setNavigationItemSelectedListener(this); 66 | } 67 | 68 | @Override 69 | public boolean onNavigationItemSelected(@NonNull MenuItem item) { 70 | drawerLayout.closeDrawer(GravityCompat.START); 71 | return true; 72 | } 73 | 74 | private void initBaseFragment(Bundle savedInstanceState) { 75 | if (getIntent().hasExtra(Const.DETAIL_ELEMENT)) { 76 | fragmentBackround.setBackground(new BitmapDrawable(getResources(), BitmapUtil.fetchBitmapFromIntent(getIntent()))); 77 | } 78 | 79 | Fragment fragment = null; 80 | if (savedInstanceState != null) { 81 | fragment = getFragmentManager().findFragmentByTag(BASE_FRAGMENT); 82 | } 83 | if (fragment == null) 84 | fragment = getBaseFragment(); 85 | setBaseFragment(fragment); 86 | } 87 | 88 | protected Fragment getBaseFragment() { 89 | int fragmentResourceId = getIntent().getIntExtra(Const.FRAGMENT_RES_ID, R.layout.fragment_home); 90 | switch (fragmentResourceId) { 91 | case R.layout.fragment_home: 92 | default: 93 | return new HomeFragment(); 94 | } 95 | } 96 | 97 | public void setBaseFragment(Fragment fragment) { 98 | if (fragment == null ) return; 99 | FragmentTransaction transaction = getFragmentManager().beginTransaction(); 100 | transaction.replace(R.id.base_fragment, fragment, BASE_FRAGMENT); 101 | transaction.commit(); 102 | } 103 | 104 | public boolean animateHomeIcon(MaterialMenuDrawable.IconState iconState) { 105 | if (currentIconState == iconState) return false; 106 | currentIconState = iconState; 107 | homeButton.animateIconState(currentIconState); 108 | return true; 109 | } 110 | 111 | public void setHomeIcon(MaterialMenuDrawable.IconState iconState) { 112 | if (currentIconState == iconState) return; 113 | currentIconState = iconState; 114 | homeButton.setIconState(currentIconState); 115 | } 116 | 117 | @Override 118 | public boolean onBeforeBack() { 119 | ActivityCompat.finishAfterTransition(this); 120 | return false; 121 | } 122 | 123 | @Override 124 | public void onBackPressed() { 125 | if (drawerLayout.isDrawerOpen(GravityCompat.START)) 126 | drawerLayout.closeDrawer(GravityCompat.START); 127 | else 128 | super.onBackPressed(); 129 | } 130 | 131 | @Override 132 | public void onNetworkConnectionChanged(boolean isConnected) { 133 | if (!isConnected) 134 | showSnackBar("INTERNET NOT FOUND", Snackbar.LENGTH_SHORT); 135 | else 136 | showSnackBar("INTERNET CONNECTED", Snackbar.LENGTH_SHORT); 137 | } 138 | 139 | public static MainActivity of(Activity activity) { 140 | return (MainActivity) activity; 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/ui/adapter/HomeAdapter.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.ui.adapter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.graphics.Palette; 8 | import android.util.Log; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.ImageView; 13 | import android.widget.RelativeLayout; 14 | import android.widget.TextView; 15 | 16 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 17 | import com.bumptech.glide.load.resource.bitmap.BitmapTransitionOptions; 18 | import com.bumptech.glide.request.target.BitmapImageViewTarget; 19 | import com.bumptech.glide.request.transition.Transition; 20 | import com.hendyghsta.parsinghtml.R; 21 | import com.hendyghsta.parsinghtml.common.GlideApp; 22 | import com.hendyghsta.parsinghtml.data.model.ListHome; 23 | 24 | import butterknife.BindView; 25 | 26 | /** 27 | * Created by hendyghsta on 08/31/2018. 28 | */ 29 | public class HomeAdapter extends MainAdapter{ 30 | 31 | private static final String TAG = HomeAdapter.class.getSimpleName(); 32 | private Context context; 33 | 34 | public HomeAdapter(Context context) { 35 | super(context); 36 | this.context = context; 37 | } 38 | 39 | @NonNull 40 | @Override 41 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 42 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_home, parent, false); 43 | return new HomeHolder(view); 44 | } 45 | 46 | 47 | //TODO 48 | public class HomeHolder extends MainAdapter.ViewHolder { 49 | 50 | @BindView(R.id.image_view) ImageView mImg; 51 | @BindView(R.id.title_view) TextView mTitle; 52 | @BindView(R.id.qt_view) TextView mQuality; 53 | @BindView(R.id.item_card) RelativeLayout mBg; 54 | 55 | HomeHolder(View itemView) { 56 | super(itemView); 57 | } 58 | 59 | @Override 60 | public void populate(ListHome i) { 61 | Log.d(TAG,i.toString()); 62 | mTitle.setText(i.title); 63 | mQuality.setText(i.quality); 64 | 65 | if (i.thumbnail != null) { 66 | GlideApp.with(context).asBitmap() 67 | .load("https:"+i.thumbnail) 68 | .centerCrop() 69 | .transition(BitmapTransitionOptions.withCrossFade()) 70 | .diskCacheStrategy(DiskCacheStrategy.ALL) 71 | .into(new BitmapImageViewTarget(mImg) { 72 | @Override 73 | public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { 74 | super.onResourceReady(resource, transition); 75 | Palette.from(resource).generate(palette -> mBg.setBackgroundColor(palette.getVibrantColor(context.getResources().getColor(R.color.colorPrimary)))); 76 | } 77 | }); 78 | } 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/ui/adapter/MainAdapter.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.ui.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.util.SparseBooleanArray; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | import com.hendyghsta.parsinghtml.R; 12 | 13 | import java.util.ArrayList; 14 | import java.util.Collections; 15 | import java.util.List; 16 | 17 | import butterknife.ButterKnife; 18 | 19 | 20 | public class MainAdapter extends RecyclerView.Adapter.ViewHolder> { 21 | 22 | private static final String TAG = MainAdapter.class.getSimpleName(); 23 | private List items = Collections.emptyList(); 24 | private SparseBooleanArray selectedItems; 25 | private OnItemClickListener onItemClickListener; 26 | private Context context; 27 | 28 | protected MainAdapter(Context context){ 29 | this.context = context; 30 | } 31 | 32 | @NonNull 33 | @Override 34 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 35 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_home, parent, false); 36 | return new ViewHolder(view); 37 | } 38 | 39 | @Override 40 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 41 | holder.populate(items.get(position)); 42 | } 43 | 44 | @Override 45 | public int getItemCount() { 46 | return items.size(); 47 | } 48 | 49 | public void updateList(List list) { 50 | this.items = list; 51 | notifyDataSetChanged(); 52 | } 53 | 54 | public void loadMoreList(List list){ 55 | int prevSize = getItemCount(); 56 | this.items.addAll(list); 57 | notifyItemRangeInserted(prevSize, list.size()); 58 | } 59 | 60 | public void removeList() { 61 | int size = getItemCount(); 62 | items.clear(); 63 | notifyItemRangeRemoved(0, size); 64 | } 65 | 66 | public void toggleSelection(int pos) { 67 | if (selectedItems.get(pos, false)) { 68 | selectedItems.delete(pos); 69 | } 70 | else { 71 | selectedItems.put(pos, true); 72 | } 73 | notifyItemChanged(pos); 74 | } 75 | 76 | public void clearSelections() { 77 | selectedItems.clear(); 78 | notifyDataSetChanged(); 79 | } 80 | 81 | public int getSelectedItemCount() { 82 | return selectedItems.size(); 83 | } 84 | 85 | public List getSelectedItems() { 86 | List items = new ArrayList<>(selectedItems.size()); 87 | for (int i = 0; i < selectedItems.size(); i++) { 88 | items.add(selectedItems.keyAt(i)); 89 | } 90 | return items; 91 | } 92 | 93 | public interface OnItemClickListener { 94 | void onItemClick(View view, T item, boolean isLongClick); 95 | } 96 | 97 | public void setOnItemClickListener(final OnItemClickListener onItemClickListener) { 98 | this.onItemClickListener = onItemClickListener; 99 | } 100 | 101 | 102 | public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener{ 103 | 104 | ViewHolder(View itemView) { 105 | super(itemView); 106 | ButterKnife.bind(this, itemView); 107 | itemView.setOnClickListener(this); 108 | itemView.setOnLongClickListener(this); 109 | } 110 | 111 | public void populate(T item) { 112 | } 113 | 114 | @Override 115 | public void onClick(View v) { 116 | handleClick(v, false); 117 | } 118 | 119 | @Override 120 | public boolean onLongClick(View v) { 121 | return handleClick(v, true); 122 | } 123 | 124 | private boolean handleClick(View v, boolean isLongClick) { 125 | if (onItemClickListener != null) { 126 | onItemClickListener.onItemClick(v, items.get(getAdapterPosition()), isLongClick); 127 | return true; 128 | } 129 | return false; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/ui/fragment/home/HomeContract.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.ui.fragment.home; 2 | 3 | import com.hendyghsta.parsinghtml.common.mvp.IBasePresenter; 4 | import com.hendyghsta.parsinghtml.common.mvp.IBaseView; 5 | import com.hendyghsta.parsinghtml.data.model.ListHome; 6 | 7 | import java.util.List; 8 | 9 | public interface HomeContract { 10 | interface View extends IBaseView { 11 | void setLastest(List items); 12 | } 13 | 14 | interface Presenter extends IBasePresenter { 15 | void getLastest(int page); 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/ui/fragment/home/HomeFragment.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.ui.fragment.home; 2 | 3 | import android.os.Bundle; 4 | import android.os.Handler; 5 | import android.support.design.widget.CoordinatorLayout; 6 | import android.support.v4.view.GravityCompat; 7 | import android.support.v7.widget.GridLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.view.LayoutInflater; 10 | import android.view.Menu; 11 | import android.view.MenuInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.view.animation.DecelerateInterpolator; 15 | import android.widget.RelativeLayout; 16 | 17 | import com.balysv.materialmenu.MaterialMenuDrawable; 18 | import com.hendyghsta.parsinghtml.R; 19 | import com.hendyghsta.parsinghtml.common.transition.Navigator; 20 | import com.hendyghsta.parsinghtml.common.transition.TransitionHelper; 21 | import com.hendyghsta.parsinghtml.data.model.ListHome; 22 | import com.hendyghsta.parsinghtml.ui.activity.MainActivity; 23 | import com.hendyghsta.parsinghtml.ui.adapter.HomeAdapter; 24 | import com.hendyghsta.parsinghtml.ui.adapter.MainAdapter; 25 | import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout; 26 | import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayoutDirection; 27 | 28 | import java.util.List; 29 | 30 | import butterknife.BindView; 31 | import butterknife.ButterKnife; 32 | 33 | public class HomeFragment extends TransitionHelper.BaseFragment implements 34 | HomeContract.View,SwipyRefreshLayout.OnRefreshListener,MainAdapter.OnItemClickListener { 35 | 36 | @BindView(R.id.parent_layout)CoordinatorLayout parentLayout; 37 | @BindView(R.id.detail_layout)RelativeLayout detailLayout; 38 | @BindView(R.id.swify)SwipyRefreshLayout swify; 39 | @BindView(R.id.recycler)RecyclerView recyclerView; 40 | private HomeContract.Presenter presenter; 41 | private HomeAdapter adapter; 42 | private int page = 1; 43 | 44 | @Override 45 | public void onCreate(Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | presenter = new HomePresenter(this); 48 | } 49 | 50 | @Override 51 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 52 | View v = inflater.inflate(R.layout.fragment_home, container, false); 53 | ButterKnife.bind(this, v); 54 | setHasOptionsMenu(true); 55 | initBody(); 56 | return v; 57 | } 58 | 59 | @Override 60 | public void onViewCreated(View view, Bundle savedInstanceState) { 61 | super.onViewCreated(view, savedInstanceState); 62 | swify.setColorSchemeResources(R.color.colorPrimary); 63 | swify.setOnRefreshListener(this); 64 | setRecycler(); 65 | new Handler().postDelayed(() -> { 66 | swify.setRefreshing(true); 67 | onRefresh(SwipyRefreshLayoutDirection.TOP); 68 | },500); 69 | } 70 | 71 | private void setRecycler(){ 72 | adapter = new HomeAdapter(getActivity()); 73 | adapter.setOnItemClickListener(this); 74 | recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),2)); 75 | recyclerView.setHasFixedSize(true); 76 | recyclerView.setAdapter(adapter); 77 | recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { 78 | @Override 79 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 80 | super.onScrolled(recyclerView, dx, dy); 81 | int visibleItemCount = recyclerView.getLayoutManager().getChildCount(); 82 | int totalItemCount = recyclerView.getLayoutManager().getItemCount(); 83 | int firstVisibleItemPosition = ((GridLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition(); 84 | if (!swify.isRefreshing()){ 85 | if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) { 86 | swify.setRefreshing(true); 87 | onRefresh(SwipyRefreshLayoutDirection.BOTTOM); 88 | } 89 | } 90 | } 91 | }); 92 | } 93 | 94 | @Override 95 | public void onRefresh(SwipyRefreshLayoutDirection direction) { 96 | if (direction == SwipyRefreshLayoutDirection.TOP) { 97 | new Handler().postDelayed(() -> { 98 | if (adapter.getItemCount()>0) adapter.removeList(); 99 | page = 1; 100 | presenter.getLastest(page); 101 | }, 500); 102 | } 103 | 104 | if (direction == SwipyRefreshLayoutDirection.BOTTOM) { 105 | new Handler().postDelayed(() -> { 106 | page = page+1; 107 | presenter.getLastest(page); 108 | }, 500); 109 | } 110 | } 111 | 112 | @Override 113 | public void setLastest(List items) { 114 | if (adapter.getItemCount() > 0) { 115 | adapter.notifyDataSetChanged(); 116 | adapter.loadMoreList(items); 117 | }else 118 | adapter.updateList(items); 119 | swify.setRefreshing(false); 120 | } 121 | 122 | @Override 123 | public void onItemClick(View view, ListHome item, boolean isLongClick) { 124 | showToastMessage(item.url); 125 | } 126 | 127 | @Override 128 | public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 129 | inflater.inflate(R.menu.menu_home, menu); 130 | super.onCreateOptionsMenu(menu, inflater); 131 | } 132 | 133 | private void initBody() { 134 | parentLayout.setAlpha(0); 135 | parentLayout.setTranslationY(100); 136 | new Handler().postDelayed(() -> parentLayout.animate() 137 | .alpha(1) 138 | .setStartDelay(Navigator.ANIM_DURATION / 3) 139 | .setDuration(Navigator.ANIM_DURATION * 5) 140 | .setInterpolator(new DecelerateInterpolator(9)) 141 | .translationY(0) 142 | .start(), 200); 143 | } 144 | 145 | @Override 146 | public boolean onBeforeBack() { 147 | MainActivity activity = MainActivity.of(getActivity()); 148 | if (!activity.animateHomeIcon(MaterialMenuDrawable.IconState.BURGER)) { 149 | activity.drawerLayout.openDrawer(GravityCompat.START); 150 | } 151 | return super.onBeforeBack(); 152 | } 153 | 154 | } -------------------------------------------------------------------------------- /app/src/main/java/com/hendyghsta/parsinghtml/ui/fragment/home/HomePresenter.java: -------------------------------------------------------------------------------- 1 | package com.hendyghsta.parsinghtml.ui.fragment.home; 2 | 3 | import com.hendyghsta.parsinghtml.common.Const; 4 | import com.hendyghsta.parsinghtml.common.mvp.BasePresenter; 5 | import com.hendyghsta.parsinghtml.data.api.Jso; 6 | import com.hendyghsta.parsinghtml.data.api.ListResponse; 7 | import com.hendyghsta.parsinghtml.data.model.ListHome; 8 | 9 | import java.util.List; 10 | 11 | import io.reactivex.android.schedulers.AndroidSchedulers; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | public class HomePresenter extends BasePresenter implements HomeContract.Presenter { 15 | 16 | public HomePresenter(HomeContract.View view) { 17 | this.view = view; 18 | } 19 | 20 | @Override 21 | public void getLastest(int page) { 22 | Jso.web(Const.URL+"/page/"+String.valueOf(page)) 23 | .homeLastest().toList() 24 | .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) 25 | .subscribe(new ListResponse(view.getActivity()){ 26 | @Override 27 | public void onSuccess(List list) { 28 | view.setLastest(list); 29 | } 30 | }); 31 | } 32 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/scale_down.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/anim/scale_up.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_up.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 | 68 | 70 | 72 | 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 19 | 20 | 21 | 22 | 27 | 28 | 32 | 33 | 39 | 40 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 18 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 19 | 20 | 29 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toolbar_container.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 24 | 25 | 33 | 34 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hendyghsta/ParsingHTML/05b3a2049503daabb2bd633f90b20365c5fa2feb/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | #EEEEEE 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Parsing HTML 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 22 | 23 | 26 | 27 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.2.0' 11 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 12 | 13 | 14 | // NOTE: Do not place your application dependencies here; they belong 15 | // in the individual module build.gradle files 16 | } 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | google() 22 | jcenter() 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | 15 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /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 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 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 Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------