├── .gitignore ├── DynamicBox ├── .gitignore ├── build.gradle ├── gradle.properties └── src │ └── main │ ├── .settings │ └── org.eclipse.jdt.core.prefs │ ├── AndroidManifest.xml │ ├── java │ └── mehdi │ │ └── sakout │ │ └── dynamicbox │ │ └── DynamicBox.java │ └── res │ ├── layout │ ├── exception_failure.xml │ ├── exception_loading_content.xml │ └── exception_no_internet.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── DynamicBoxExample ├── .gitignore ├── build.gradle ├── gradle.properties └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── mehdi │ │ └── sakout │ │ └── dynamicboxexample │ │ ├── ActivityActivity.java │ │ ├── ListViewActivity.java │ │ └── MainActivity.java │ └── res │ ├── drawable-hdpi │ ├── green_monster.png │ ├── ic_launcher.png │ ├── nature.jpg │ └── saxophone.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── layout │ ├── activity_activity.xml │ ├── activity_listview.xml │ ├── activity_main.xml │ └── music_not_found.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── maven_push.gradle ├── screenshots ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── apps │ └── com.mobiacube.elbotola.png ├── cat-box-icon.png ├── demo_gmail_no_messages.png ├── demo_gplay_no_internet.png ├── demo_popcorn_loading.png └── demo_slack_loading.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | #built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Windows thumbnail db 19 | Thumbs.db 20 | 21 | # OSX files 22 | .DS_Store 23 | 24 | # Eclipse project files 25 | .classpath 26 | .project 27 | 28 | # Android Studio 29 | .idea 30 | .gradle 31 | build/ 32 | 33 | project.properties 34 | out 35 | *.iml -------------------------------------------------------------------------------- /DynamicBox/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /DynamicBox/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'android-library' 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | android { 8 | compileSdkVersion 22 9 | buildToolsVersion "22.0.1" 10 | 11 | defaultConfig { 12 | minSdkVersion 8 13 | targetSdkVersion 22 14 | versionCode 2 15 | versionName "1.2" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | compile fileTree(dir: 'libs', include: ['*.jar']) 27 | } 28 | 29 | apply from: '../maven_push.gradle' -------------------------------------------------------------------------------- /DynamicBox/gradle.properties: -------------------------------------------------------------------------------- 1 | VERSION_NAME=1.2 2 | VERSION_CODE=4 3 | GROUP=com.github.medyo 4 | POM_DESCRIPTION=Dynamicbox lib 5 | POM_URL=https://github.com/medyo/dynamicbox 6 | POM_SCM_URL=https://github.com/medyo/dynamicbox 7 | POM_SCM_CONNECTION=scm:git@github.com:medyo/dynamicbox.git 8 | POM_SCM_DEV_CONNECTION=scm:git@github.com:medyo/dynamicbox.git 9 | POM_LICENCE_NAME=MIT 10 | POM_LICENCE_URL=http://opensource.org/licenses/MIT 11 | POM_LICENCE_DIST=repo 12 | POM_DEVELOPER_ID=medyo 13 | POM_DEVELOPER_NAME=Mehdi Sakout 14 | 15 | POM_NAME=Dynamicbox Library 16 | POM_ARTIFACT_ID=dynamicbox 17 | POM_PACKAGING=aar -------------------------------------------------------------------------------- /DynamicBox/src/main/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /DynamicBox/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /DynamicBox/src/main/java/mehdi/sakout/dynamicbox/DynamicBox.java: -------------------------------------------------------------------------------- 1 | package mehdi.sakout.dynamicbox; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Locale; 6 | import android.app.Activity; 7 | import android.content.Context; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.AbsListView; 12 | import android.widget.RelativeLayout; 13 | import android.widget.TextView; 14 | import android.widget.LinearLayout.LayoutParams; 15 | import android.widget.ViewSwitcher; 16 | 17 | /** 18 | * 19 | * @author Mehdi Sakout 20 | * @author Danny Tsegai 21 | * 22 | */ 23 | public class DynamicBox { 24 | 25 | private View mTargetView; 26 | private View.OnClickListener mClickListener; 27 | private Context mContext; 28 | private LayoutInflater mInflater; 29 | private RelativeLayout mContainer; 30 | private ArrayList mCustomViews; 31 | private ArrayList mDefaultViews; 32 | private ViewSwitcher mSwitcher; 33 | 34 | // Default Tags 35 | private final String TAG_INTERNET_OFF = "INTERNET_OFF"; 36 | private final String TAG_LOADING_CONTENT = "LOADING_CONTENT"; 37 | private final String TAG_OTHER_EXCEPTION = "OTHER_EXCEPTION"; 38 | 39 | private final String[] mSupportedAbsListViews = new String[]{"listview","gridview","expandablelistview"}; 40 | private final String[] mSupportedViews = new String[]{"linearlayout","relativelayout", "framelayout", "scrollview", "recyclerview", "viewgroup"}; 41 | 42 | public DynamicBox(Context context, View targetView){ 43 | this.mContext = context; 44 | this.mInflater = ((Activity)mContext).getLayoutInflater(); 45 | this.mTargetView = targetView; 46 | this.mContainer = new RelativeLayout(mContext); 47 | this.mCustomViews = new ArrayList(); 48 | this.mDefaultViews = new ArrayList(); 49 | 50 | Class viewClass = mTargetView.getClass(); 51 | Class superViewClass = viewClass.getSuperclass(); 52 | String viewType = viewClass.getName().substring(viewClass.getName().lastIndexOf('.')+1).toLowerCase(Locale.getDefault()); 53 | String superViewType = superViewClass.getName().substring(superViewClass.getName().lastIndexOf('.')+1).toLowerCase(Locale.getDefault()); 54 | 55 | if(Arrays.asList(mSupportedAbsListViews).contains(viewType)|| Arrays.asList(mSupportedAbsListViews).contains(superViewType)) 56 | initializeAbsListView(); 57 | else if(Arrays.asList(mSupportedViews).contains(viewType)|| Arrays.asList(mSupportedViews).contains(superViewType)) 58 | initializeViewContainer(); 59 | else 60 | throw new IllegalArgumentException("TargetView type ["+superViewType+"] is not supported !"); 61 | 62 | } 63 | 64 | public DynamicBox(Context context,int viewID){ 65 | this.mContext = context; 66 | this.mInflater = ((Activity)mContext).getLayoutInflater(); 67 | this.mTargetView = mInflater.inflate(viewID, null, false); 68 | this.mContainer = new RelativeLayout(mContext); 69 | this.mCustomViews = new ArrayList(); 70 | this.mDefaultViews = new ArrayList(); 71 | 72 | Class viewClass = mTargetView.getClass(); 73 | Class superViewClass = viewClass.getSuperclass(); 74 | String viewType = viewClass.getName().substring(viewClass.getName().lastIndexOf('.') + 1).toLowerCase(Locale.getDefault()); 75 | String superViewType = superViewClass.getName().substring(superViewClass.getName().lastIndexOf('.')+1).toLowerCase(Locale.getDefault()); 76 | 77 | if(Arrays.asList(mSupportedAbsListViews).contains(viewType)|| Arrays.asList(mSupportedAbsListViews).contains(superViewType)) 78 | initializeAbsListView(); 79 | else if(Arrays.asList(mSupportedViews).contains(viewType)|| Arrays.asList(mSupportedViews).contains(superViewType)) 80 | initializeViewContainer(); 81 | else 82 | throw new IllegalArgumentException("TargetView type ["+superViewType+"] is not supported !"); 83 | 84 | } 85 | 86 | private void initializeViewContainer(){ 87 | 88 | setDefaultViews(); 89 | 90 | mSwitcher = new ViewSwitcher(mContext); 91 | ViewSwitcher.LayoutParams params = new ViewSwitcher.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 92 | mSwitcher.setLayoutParams(params); 93 | 94 | ViewGroup group = (ViewGroup)mTargetView.getParent(); 95 | int index = 0; 96 | Clonner target= new Clonner(mTargetView); 97 | if(group!=null){ 98 | index = group.indexOfChild(mTargetView); 99 | group.removeView(mTargetView); 100 | 101 | } 102 | 103 | mSwitcher.addView(mContainer,0); 104 | mSwitcher.addView(target.getmView(),1); 105 | mSwitcher.setDisplayedChild(1); 106 | 107 | if(group!=null){ 108 | group.addView(mSwitcher,index); 109 | }else{ 110 | ((Activity)mContext).setContentView(mSwitcher); 111 | } 112 | 113 | 114 | } 115 | 116 | private void setDefaultViews(){ 117 | View mLayoutInternetOff = initView(R.layout.exception_no_internet,TAG_INTERNET_OFF); 118 | View mLayoutLoadingContent = initView(R.layout.exception_loading_content,TAG_LOADING_CONTENT); 119 | View mLayoutOther = initView(R.layout.exception_failure,TAG_OTHER_EXCEPTION); 120 | 121 | mDefaultViews.add(0,mLayoutInternetOff); 122 | mDefaultViews.add(1,mLayoutLoadingContent); 123 | mDefaultViews.add(2,mLayoutOther); 124 | 125 | // Hide all layouts at first initialization 126 | mLayoutInternetOff.setVisibility(View.GONE); 127 | mLayoutLoadingContent.setVisibility(View.GONE); 128 | mLayoutOther.setVisibility(View.GONE); 129 | 130 | // init Layout params 131 | RelativeLayout.LayoutParams containerParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 132 | containerParams.addRule(RelativeLayout.CENTER_HORIZONTAL); 133 | containerParams.addRule(RelativeLayout.CENTER_VERTICAL); 134 | 135 | // init new RelativeLayout Wrapper 136 | mContainer.setLayoutParams(containerParams); 137 | 138 | // Add default views 139 | mContainer.addView(mLayoutLoadingContent); 140 | mContainer.addView(mLayoutInternetOff); 141 | mContainer.addView(mLayoutOther); 142 | } 143 | 144 | private void initializeAbsListView(){ 145 | 146 | setDefaultViews(); 147 | 148 | AbsListView abslistview = (AbsListView)mTargetView; 149 | abslistview.setVisibility(View.GONE); 150 | ViewGroup parent = (ViewGroup) abslistview.getParent(); 151 | if(mContainer!=null){ 152 | parent.addView(mContainer); 153 | abslistview.setEmptyView(mContainer); 154 | }else 155 | throw new IllegalArgumentException("mContainer is null !"); 156 | 157 | } 158 | 159 | public void showLoadingLayout(){ 160 | show(TAG_LOADING_CONTENT); 161 | } 162 | public void showInternetOffLayout(){ 163 | show(TAG_INTERNET_OFF); 164 | } 165 | public void showExceptionLayout(){ 166 | show(TAG_OTHER_EXCEPTION); 167 | } 168 | public void showCustomView(String tag){ 169 | show(tag); 170 | } 171 | 172 | public void hideAll(){ 173 | ArrayList views = new ArrayList(mDefaultViews); 174 | views.addAll(mCustomViews); 175 | for(View view : views){ 176 | view.setVisibility(View.GONE); 177 | } 178 | if(mSwitcher!=null){ 179 | mSwitcher.setDisplayedChild(1); 180 | } 181 | } 182 | private void show(String tag){ 183 | ArrayList views = new ArrayList(mDefaultViews); 184 | views.addAll(mCustomViews); 185 | for(View view : views){ 186 | if(view.getTag()!=null && view.getTag().toString().equals(tag)){ 187 | view.setVisibility(View.VISIBLE); 188 | }else{ 189 | view.setVisibility(View.GONE); 190 | } 191 | } 192 | if(mSwitcher!=null && mSwitcher.getDisplayedChild()!=0){ 193 | mSwitcher.setDisplayedChild(0); 194 | } 195 | } 196 | /** 197 | * Return a view based on layout id 198 | * @param layout Layout Id 199 | * @param tag Layout Tag 200 | * @return View 201 | */ 202 | private View initView(int layout, String tag){ 203 | View view = mInflater.inflate(layout, null,false); 204 | 205 | view.setTag(tag); 206 | view.setVisibility(View.GONE); 207 | 208 | View buttonView = view.findViewById(R.id.exception_button); 209 | if(buttonView!=null) 210 | buttonView.setOnClickListener(this.mClickListener); 211 | 212 | return view; 213 | } 214 | /** 215 | * 216 | * @see Android Design Guidelines for Activity Circles 217 | * @deprecated This method has been deprecated because it does not adhere to the Android design guidelines. Activity circle's should not display any text. 218 | * 219 | */ 220 | public void setLoadingMessage(String message){ 221 | ((TextView)mDefaultViews.get(1).findViewById(R.id.exception_message)).setText(message); 222 | } 223 | public void setInternetOffMessage(String message){ 224 | ((TextView)mDefaultViews.get(0).findViewById(R.id.exception_message)).setText(message); 225 | } 226 | public void setOtherExceptionMessage(String message){ 227 | ((TextView)mDefaultViews.get(2).findViewById(R.id.exception_message)).setText(message); 228 | } 229 | public void setInternetOffTitle(String message){ 230 | ((TextView)mDefaultViews.get(0).findViewById(R.id.exception_title)).setText(message); 231 | } 232 | public void setOtherExceptionTitle(String message){ 233 | ((TextView)mDefaultViews.get(2).findViewById(R.id.exception_title)).setText(message); 234 | } 235 | public void setClickListener(View.OnClickListener clickListener){ 236 | 237 | this.mClickListener = clickListener; 238 | 239 | for(View view : mDefaultViews){ 240 | View buttonView = view.findViewById(R.id.exception_button); 241 | if(buttonView!=null) 242 | buttonView.setOnClickListener(this.mClickListener); 243 | } 244 | 245 | 246 | } 247 | 248 | public void addCustomView(View customView,String tag){ 249 | 250 | customView.setTag(tag); 251 | customView.setVisibility(View.GONE); 252 | mCustomViews.add(customView); 253 | mContainer.addView(customView); 254 | } 255 | private class Clonner{ 256 | private View mView; 257 | 258 | public Clonner(View view){ 259 | this.setmView(view); 260 | } 261 | 262 | public View getmView() { 263 | return mView; 264 | } 265 | 266 | public void setmView(View mView) { 267 | this.mView = mView; 268 | } 269 | } 270 | } -------------------------------------------------------------------------------- /DynamicBox/src/main/res/layout/exception_failure.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 22 | 23 | 29 | 30 | 34 | 35 |