diff --git a/app/build.gradle b/app/build.gradle index ef94b8d..fd3cac0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,7 +9,7 @@ android { applicationId "com.sjapps.jsonlist" minSdk 23 targetSdk 34 - versionCode 6 + versionCode 7 versionName "1.4" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/com/sjapps/adapters/ListAdapter.java b/app/src/main/java/com/sjapps/adapters/ListAdapter.java index da9ea4b..f5110ed 100644 --- a/app/src/main/java/com/sjapps/adapters/ListAdapter.java +++ b/app/src/main/java/com/sjapps/adapters/ListAdapter.java @@ -3,13 +3,25 @@ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; +import android.graphics.Color; +import android.os.Handler; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.BaseAdapter; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; +import android.view.animation.OvershootInterpolator; import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.AnimRes; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + import com.sjapps.jsonlist.java.JsonData; import com.sjapps.jsonlist.java.ListItem; import com.sjapps.jsonlist.MainActivity; @@ -17,13 +29,74 @@ import java.util.ArrayList; -public class ListAdapter extends BaseAdapter { +public class ListAdapter extends RecyclerView.Adapter { + + Handler handler = new Handler(); ArrayList list; Context context; MainActivity activity; String path; public int selectedItem = -1; + public int highlightedItem = -1; + + + + static class ViewHolderShort extends RecyclerView.ViewHolder{ + + TextView title; + + public ViewHolderShort(View itemView) { + super(itemView); + title = itemView.findViewById(R.id.itemName); + } + public TextView getTitleTxt(){ + return title; + } + + public View getView(){ + return itemView; + } + + } + + static class ViewHolderLong extends RecyclerView.ViewHolder{ + + TextView title, value; + + public ViewHolderLong(View itemView) { + super(itemView); + title = itemView.findViewById(R.id.itemName); + value = itemView.findViewById(R.id.itemValue); + } + public TextView getTitleTxt(){ + return title; + } + + public TextView getValueTxt(){ + return value; + } + + public View getView(){ + return itemView; + } + + } + + static class ViewHolderSpace extends RecyclerView.ViewHolder{ + + + public ViewHolderSpace(View itemView) { + super(itemView); + + } + + public View getView(){ + return itemView; + } + + } + public ListAdapter(ArrayList list, Context context,String path){ this.list = list; @@ -33,70 +106,82 @@ public ListAdapter(ArrayList list, Context context,String path){ } @Override - public int getCount() { - if (list == null) - return 0; - - if (list.size() == 0) - return 0; + public int getItemViewType(int position) { - if (!list.get(getLast()).isSpace()) - return list.size(); - return getLast(); - } + ListItem item = list.get(position); - @Override - public Object getItem(int i) { - return list.get(i); + return (item.isArray() || item.isObject())?0:item.isSpace()?2:1; } + @NonNull @Override - public long getItemId(int i) { - return i; - } - - private int getLast(){ - return (list.size()>0?list.size()-1:0); + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + switch (viewType) { + case 0: + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_layout,parent,false); + return new ViewHolderShort(view); + case 1: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_layout2,parent,false); + return new ViewHolderLong(view); + case 2: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.space_layout,parent,false); + return new ViewHolderSpace(view); + } + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_layout,parent,false); + return new ViewHolderShort(view); } - @Override - public View getView(int position, View convertView, ViewGroup parent) { + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int pos) { - ListItem item = list.get(position); + ListItem item = list.get(pos); if(item.isSpace()) { - return LayoutInflater.from(context).inflate(R.layout.space_layout, parent, false); + return; } + + int position = pos; + if (item.isArray() || item.isObject()) { - View view = LayoutInflater.from(context).inflate(R.layout.list_layout,parent,false); - TextView titleTxt = view.findViewById(R.id.itemName); + ViewHolderShort currentHolder = (ViewHolderShort) holder; + + TextView titleTxt = currentHolder.getTitleTxt(); titleTxt.setText(item.getName()); + View view = currentHolder.getView(); + if (selectedItem == position){ view.findViewById(R.id.copyBtn).setVisibility(View.VISIBLE); + }else view.findViewById(R.id.copyBtn).setVisibility(View.GONE); + + if (highlightedItem == position){ + setAnimation(context,view,R.anim.button_prev,new OvershootInterpolator()); + highlightedItem = -1; } + String newPath = path + (path.equals("") ? "": "///" + (item.getId()!=-1?"{" + item.getId() + "}":"")) + item.getName(); - view.findViewById(R.id.btn).setOnClickListener(view1 -> activity.open(JsonData.getPathFormat(newPath),newPath)); + view.findViewById(R.id.btn).setOnClickListener(view1 -> activity.open(JsonData.getPathFormat(newPath),newPath,position)); view.findViewById(R.id.copyBtn).setOnClickListener(v -> { ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clipData = ClipData.newPlainText("Text",item.getName()); - clipboard.setPrimaryClip(clipData); - Toast.makeText(v.getContext(),"Copied to clipboard",Toast.LENGTH_SHORT).show(); - selectedItem = -1; - notifyDataSetChanged(); + ClipData clipData = ClipData.newPlainText("Text",item.getName()); + clipboard.setPrimaryClip(clipData); + Toast.makeText(v.getContext(),"Copied to clipboard",Toast.LENGTH_SHORT).show(); + selectedItem = -1; + notifyItemChanged(position); }); view.findViewById(R.id.btn).setOnLongClickListener(v -> { + notifyItemChanged(selectedItem); selectedItem = position; - notifyDataSetChanged(); + notifyItemChanged(position); return true; }); - return view; - + return; } - View view = LayoutInflater.from(context).inflate(R.layout.list_layout2,parent,false); - TextView titleTxt = view.findViewById(R.id.itemName); - TextView valueTxt = view.findViewById(R.id.itemValue); + + ViewHolderLong currentHolder = (ViewHolderLong) holder; + View view = currentHolder.getView(); + TextView titleTxt = currentHolder.getTitleTxt(); + TextView valueTxt = currentHolder.getValueTxt(); if (item.getName() == null) titleTxt.setVisibility(View.GONE); else { @@ -107,6 +192,38 @@ public View getView(int position, View convertView, ViewGroup parent) { valueTxt.setText(item.getValue().isEmpty() ? "\"\"" : item.getValue()); - return view; + } + + @Override + public int getItemCount() { + if (list == null) + return 0; + + if (list.size() == 0) + return 0; + + if (!list.get(getLast()).isSpace()) + return list.size(); + return getLast(); + } + + private int getLast(){ + return (list.size()>0?list.size()-1:0); + } + + @Override + public long getItemId(int position) { + return position; + } + + public void setHighlightItem(int position){ + highlightedItem = position; + } + + public static void setAnimation(Context context, @NonNull View view, @AnimRes int animationRes, Interpolator interpolator) { + Animation animation = AnimationUtils.loadAnimation(context, animationRes); + if (interpolator != null) + animation.setInterpolator(interpolator); + view.startAnimation(animation); } } diff --git a/app/src/main/java/com/sjapps/jsonlist/MainActivity.java b/app/src/main/java/com/sjapps/jsonlist/MainActivity.java index 05ffda1..79a6b5b 100644 --- a/app/src/main/java/com/sjapps/jsonlist/MainActivity.java +++ b/app/src/main/java/com/sjapps/jsonlist/MainActivity.java @@ -8,6 +8,8 @@ import androidx.annotation.AnimRes; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.app.Activity; import android.content.Context; @@ -34,7 +36,6 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.ListView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; @@ -65,7 +66,7 @@ public class MainActivity extends AppCompatActivity { ImageView fileImg; Button openFileBtn; TextView titleTxt, emptyListTxt; - ListView list; + RecyclerView list; JsonData data = new JsonData(); LinearLayout progressView; ProgressBar progressBar; @@ -190,7 +191,7 @@ public void handleOnBackPressed() { if (adapter!= null && adapter.selectedItem != -1){ adapter.selectedItem = -1; - adapter.notifyDataSetChanged(); + adapter.notifyItemRangeChanged(0,adapter.getItemCount()); return; } @@ -209,7 +210,7 @@ public void handleOnBackPressed() { TransitionManager.beginDelayedTransition(viewGroup, autoTransition); data.goBack(); - open(JsonData.getPathFormat(data.getPath()), data.getPath()); + open(JsonData.getPathFormat(data.getPath()), data.getPath(),-1); if (data.isEmptyPath()) { backBtn.setVisibility(View.GONE); } @@ -234,6 +235,7 @@ private void initialize() { menu.bringToFront(); menuBtn.bringToFront(); dropTarget = findViewById(R.id.dropTarget); + list.setLayoutManager(new LinearLayoutManager(this)); } private void open_closeMenu() { @@ -320,7 +322,7 @@ private void LoadData(String Data) { readFileThread.start(); } - public void open(String Title, String path) { + public void open(String Title, String path, int previousPosition) { TransitionManager.beginDelayedTransition(viewGroup, autoTransition); if (isMenuOpen) @@ -334,6 +336,18 @@ public void open(String Title, String path) { ArrayList arrayList = getListFromPath(path,data.getRootList()); adapter = new ListAdapter(arrayList, this, path); list.setAdapter(adapter); + + if (previousPosition == -1) { + handler.postDelayed(() -> { + list.smoothScrollToPosition(data.getPreviousPos()+2); + adapter.setHighlightItem(data.getPreviousPos()); + }, 500); + handler.postDelayed(() -> { + adapter.notifyItemChanged(data.getPreviousPos()); + }, 600); + } + else data.addPreviousPos(previousPosition); + if (arrayList.size() == 0) { emptyListTxt.setVisibility(View.VISIBLE); } diff --git a/app/src/main/java/com/sjapps/jsonlist/java/JsonData.java b/app/src/main/java/com/sjapps/jsonlist/java/JsonData.java index ceb9ec9..3093d3f 100644 --- a/app/src/main/java/com/sjapps/jsonlist/java/JsonData.java +++ b/app/src/main/java/com/sjapps/jsonlist/java/JsonData.java @@ -1,10 +1,14 @@ package com.sjapps.jsonlist.java; import java.util.ArrayList; +import java.util.Stack; public class JsonData { String path = ""; ArrayList rootList = new ArrayList<>(); + Stack previousPosStack = new Stack<>(); + + int previousPos = -1; public String getPath() { return path; @@ -41,6 +45,9 @@ public boolean isRootListNull(){ public void goBack(){ + if (!previousPosStack.isEmpty()) + previousPos = previousPosStack.pop(); + String[] pathStrings = splitPath(); clearPath(); for (int i = 0; i < pathStrings.length-1; i++) { @@ -49,6 +56,14 @@ public void goBack(){ } + public void addPreviousPos(int pos){ + previousPosStack.push(pos); + } + + public int getPreviousPos(){ + return previousPos; + } + public static String getPathFormat(String path){ String[] pathStrings = splitPath(path); StringBuilder builder = new StringBuilder(); diff --git a/app/src/main/res/anim/button_prev.xml b/app/src/main/res/anim/button_prev.xml new file mode 100644 index 0000000..5196dcb --- /dev/null +++ b/app/src/main/res/anim/button_prev.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 67736c5..15c5013 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -76,7 +76,7 @@ android:layout_height="match_parent" android:background="#70000000" android:visibility="invisible" /> -