From 7fc8804721277d1c64da93dd44243018ea77136b Mon Sep 17 00:00:00 2001 From: bret-fears Date: Mon, 3 Apr 2017 14:34:02 -0400 Subject: [PATCH] Example app controls - Add vertical view pager - Add controls fragment - Separate parent and children gridlayout from controls - Clean up continuous weighted weights --- .../spurceexampleapp/SpruceActivity.java | 65 ++- .../fragments/ControlsFragment.java | 413 ++++++++++++++++++ .../fragments/ViewFragment.java | 370 +--------------- .../pager/VerticalViewPager.java | 94 ++++ .../drawable/ic_keyboard_arrow_up_24dp.xml | 9 + app/src/main/res/layout/activity_fragment.xml | 174 -------- .../res/layout/continuous_radio_group.xml | 121 ++--- app/src/main/res/layout/controls_fragment.xml | 124 ++++++ .../main/res/layout/cornered_radio_group.xml | 7 +- .../res/layout/directional_radio_group.xml | 7 +- app/src/main/res/layout/fragment_pager.xml | 52 +++ .../res/layout/positional_radio_group.xml | 4 +- app/src/main/res/layout/view_fragment.xml | 78 ++++ app/src/main/res/values/strings.xml | 1 + 14 files changed, 917 insertions(+), 602 deletions(-) create mode 100644 app/src/main/java/com/willowtreeapps/spurceexampleapp/fragments/ControlsFragment.java create mode 100644 app/src/main/java/com/willowtreeapps/spurceexampleapp/pager/VerticalViewPager.java create mode 100644 app/src/main/res/drawable/ic_keyboard_arrow_up_24dp.xml delete mode 100644 app/src/main/res/layout/activity_fragment.xml create mode 100644 app/src/main/res/layout/controls_fragment.xml create mode 100644 app/src/main/res/layout/fragment_pager.xml create mode 100644 app/src/main/res/layout/view_fragment.xml diff --git a/app/src/main/java/com/willowtreeapps/spurceexampleapp/SpruceActivity.java b/app/src/main/java/com/willowtreeapps/spurceexampleapp/SpruceActivity.java index d41e41f..a70bace 100644 --- a/app/src/main/java/com/willowtreeapps/spurceexampleapp/SpruceActivity.java +++ b/app/src/main/java/com/willowtreeapps/spurceexampleapp/SpruceActivity.java @@ -27,36 +27,54 @@ import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Spinner; +import com.willowtreeapps.spurceexampleapp.fragments.ControlsFragment; import com.willowtreeapps.spurceexampleapp.fragments.ViewFragment; +import com.willowtreeapps.spurceexampleapp.pager.VerticalViewPager; -public class SpruceActivity extends AppCompatActivity { +import java.util.ArrayList; +import java.util.List; + +public class SpruceActivity extends AppCompatActivity + implements ViewFragment.OnParentAndChildCreationListener { + + public ViewGroup parent; + public List children = new ArrayList<>(); + public Spinner sortDropDown; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_fragment); + setContentView(R.layout.fragment_pager); FragmentManager fm = getSupportFragmentManager(); - Fragment viewFragment = fm.findFragmentById(R.id.view_fragment); - if (viewFragment == null) { - viewFragment = ViewFragment.newInstance(); - fm.beginTransaction() - .add(R.id.view_fragment, viewFragment) - .commit(); - } + VerticalViewPager verticalPager = (VerticalViewPager) findViewById(R.id.vertical_pager); + VerticalPagerAdapter adapter = new VerticalPagerAdapter(fm); + verticalPager.setAdapter(adapter); Toolbar toolBar = (Toolbar) findViewById(R.id.tool_bar); setSupportActionBar(toolBar); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayShowTitleEnabled(false); } + + sortDropDown = (Spinner) findViewById(R.id.sort_selection); + ArrayAdapter spinnerAdapter = ArrayAdapter.createFromResource(this, + R.array.sort_functions, + R.layout.spinner_item); + spinnerAdapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item); + sortDropDown.setAdapter(spinnerAdapter); } @Override @@ -77,4 +95,33 @@ public boolean onOptionsItemSelected(MenuItem item) { } return super.onOptionsItemSelected(item); } + + @Override + public void onParentAndChildrenPrepared(ViewGroup parent, List children) { + this.parent = parent; + this.children = children; + } + + private class VerticalPagerAdapter extends FragmentStatePagerAdapter { + + VerticalPagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + switch (position) { + case 1: + return ControlsFragment.newInstance(); + default: + return ViewFragment.newInstance(); + } + } + + @Override + public int getCount() { + return 2; + } + + } } diff --git a/app/src/main/java/com/willowtreeapps/spurceexampleapp/fragments/ControlsFragment.java b/app/src/main/java/com/willowtreeapps/spurceexampleapp/fragments/ControlsFragment.java new file mode 100644 index 0000000..fe12373 --- /dev/null +++ b/app/src/main/java/com/willowtreeapps/spurceexampleapp/fragments/ControlsFragment.java @@ -0,0 +1,413 @@ +/* + * Spruce + * + * Copyright (c) 2017 WillowTree, Inc. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.willowtreeapps.spurceexampleapp.fragments; + +import android.animation.Animator; +import android.os.Bundle; +import android.support.annotation.IdRes; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.GridLayout; +import android.widget.LinearLayout; +import android.widget.RadioGroup; +import android.widget.SeekBar; +import android.widget.Spinner; +import android.widget.TextView; + +import com.willowtreeapps.spruce.Spruce; +import com.willowtreeapps.spruce.animation.DefaultAnimations; +import com.willowtreeapps.spruce.sort.ContinuousSort; +import com.willowtreeapps.spruce.sort.ContinuousWeightedSort; +import com.willowtreeapps.spruce.sort.CorneredSort; +import com.willowtreeapps.spruce.sort.DefaultSort; +import com.willowtreeapps.spruce.sort.InlineSort; +import com.willowtreeapps.spruce.sort.LinearSort; +import com.willowtreeapps.spruce.sort.RadialSort; +import com.willowtreeapps.spruce.sort.RandomSort; +import com.willowtreeapps.spruce.sort.SortFunction; +import com.willowtreeapps.spurceexampleapp.R; +import com.willowtreeapps.spurceexampleapp.SpruceActivity; +import com.willowtreeapps.spurceexampleapp.widgets.RadioGroupGridLayout; + +import java.util.List; + + +public class ControlsFragment extends Fragment implements RadioGroupGridLayout.OnChangedListener { + + private static final int DEFAULT_SORT = 0; + private static final int CORNERED_SORT = 1; + private static final int CONTINUOUS_SORT = 2; + private static final int CONTINUOUS_WEIGHTED_SORT = 3; + private static final int INLINE_SORT = 4; + private static final int LINEAR_SORT = 5; + private static final int RADIAL_SORT = 6; + private static final int RANDOM_SORT = 7; + + private Animator spruceAnimator; + private SeekBar seekBar; + private Spinner sortDropDown; + private RadioGroup linearRadioGroup; + private RadioGroup corneredRadioGroup; + private RadioGroupGridLayout positionalRadioGroup; + private double verticalWeight; + private double horizontalWeight; + private CheckBox linearReversed; + private LinearLayout verticalWeightLayout; + private LinearLayout horizontalWeightLayout; + private TextView animationEndText; + private TextView seekBarTitle; + private EditText codeSample; + + private Animator[] animators; + private LinearSort.Direction direction; + private CorneredSort.Corner corner; + + private GridLayout parent; + private List children; + + public static ControlsFragment newInstance() { + return new ControlsFragment(); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) { + ViewGroup rootView = (ViewGroup) inflater + .inflate(R.layout.controls_fragment, + container, + false); + + parent = (GridLayout) ((SpruceActivity) getActivity()).parent; + children = ((SpruceActivity) getActivity()).children; + sortDropDown = ((SpruceActivity) getActivity()).sortDropDown; + + linearRadioGroup = (RadioGroup) rootView.findViewById(R.id.directional_radio_group); + corneredRadioGroup = (RadioGroup) rootView.findViewById(R.id.cornered_radio_group); + positionalRadioGroup = (RadioGroupGridLayout) rootView.findViewById(R.id.positional_radio_group); + RadioGroup verticalWeightedRadioGroup = (RadioGroup) rootView.findViewById(R.id.vertical_weighted_radio_group); + RadioGroup horizontalWeightedRadioGroup = (RadioGroup) rootView.findViewById(R.id.horizontal_weighted_radio_group); + verticalWeightLayout = (LinearLayout) rootView.findViewById(R.id.vertical_weight); + horizontalWeightLayout = (LinearLayout) rootView.findViewById(R.id.horizontal_weight); + linearReversed = (CheckBox) rootView.findViewById(R.id.linear_reversed); + seekBar = (SeekBar) rootView.findViewById(R.id.animation_seek); + animationEndText = (TextView) rootView.findViewById(R.id.animation_end); + seekBarTitle = (TextView) rootView.findViewById(R.id.seek_bar_title); + codeSample = (EditText) rootView.findViewById(R.id.code_sample); + + animators = new Animator[]{ + DefaultAnimations.shrinkAnimator(parent, /*duration=*/800), + DefaultAnimations.fadeInAnimator(parent, /*duration=*/800) + }; + + View.OnClickListener click = new View.OnClickListener() { + @Override + public void onClick(View v) { + resetChildViewsAndStartSort(); + } + }; + container.setOnClickListener(click); + parent.setOnClickListener(click); + + sortDropDown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + switch (position) { + case CORNERED_SORT: + case INLINE_SORT: + linearRadioGroup.setVisibility(View.GONE); + linearReversed.setVisibility(View.VISIBLE); + positionalRadioGroup.setVisibility(View.GONE); + verticalWeightLayout.setVisibility(View.GONE); + horizontalWeightLayout.setVisibility(View.GONE); + corneredRadioGroup.setVisibility(View.VISIBLE); + break; + case LINEAR_SORT: + linearRadioGroup.setVisibility(View.VISIBLE); + linearReversed.setVisibility(View.VISIBLE); + positionalRadioGroup.setVisibility(View.GONE); + verticalWeightLayout.setVisibility(View.GONE); + horizontalWeightLayout.setVisibility(View.GONE); + corneredRadioGroup.setVisibility(View.GONE); + break; + case CONTINUOUS_SORT: + case RADIAL_SORT: + positionalRadioGroup.setVisibility(View.VISIBLE); + verticalWeightLayout.setVisibility(View.GONE); + horizontalWeightLayout.setVisibility(View.GONE); + linearReversed.setVisibility(View.VISIBLE); + linearRadioGroup.setVisibility(View.GONE); + corneredRadioGroup.setVisibility(View.GONE); + break; + case CONTINUOUS_WEIGHTED_SORT: + positionalRadioGroup.setVisibility(View.VISIBLE); + verticalWeightLayout.setVisibility(View.VISIBLE); + horizontalWeightLayout.setVisibility(View.VISIBLE); + linearReversed.setVisibility(View.VISIBLE); + linearRadioGroup.setVisibility(View.GONE); + corneredRadioGroup.setVisibility(View.GONE); + break; + default: + linearReversed.setVisibility(View.GONE); + positionalRadioGroup.setVisibility(View.GONE); + verticalWeightLayout.setVisibility(View.GONE); + horizontalWeightLayout.setVisibility(View.GONE); + linearRadioGroup.setVisibility(View.GONE); + corneredRadioGroup.setVisibility(View.GONE); + break; + } + resetChildViewsAndStartSort(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + }); + + // set default vertical weight + verticalWeight = ContinuousWeightedSort.MEDIUM_WEIGHT; + verticalWeightedRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { + switch (checkedId) { + case R.id.vertical_light: + verticalWeight = ContinuousWeightedSort.LIGHT_WEIGHT; + break; + case R.id.vertical_medium: + verticalWeight = ContinuousWeightedSort.MEDIUM_WEIGHT; + break; + case R.id.vertical_heavy: + verticalWeight = ContinuousWeightedSort.HEAVY_WEIGHT; + break; + } + resetChildViewsAndStartSort(); + } + }); + + // set default horizontal weight + horizontalWeight = ContinuousWeightedSort.MEDIUM_WEIGHT; + horizontalWeightedRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { + switch (checkedId) { + case R.id.horizontal_light: + horizontalWeight = ContinuousWeightedSort.LIGHT_WEIGHT; + break; + case R.id.horizontal_medium: + horizontalWeight = ContinuousWeightedSort.MEDIUM_WEIGHT; + break; + case R.id.horizontal_heavy: + horizontalWeight = ContinuousWeightedSort.HEAVY_WEIGHT; + break; + } + resetChildViewsAndStartSort(); + } + }); + + // set default direction + direction = LinearSort.Direction.BOTTOM_TO_TOP; + linearRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { + switch (checkedId) { + case R.id.bottom_to_top: + direction = LinearSort.Direction.BOTTOM_TO_TOP; + break; + case R.id.top_to_bottom: + direction = LinearSort.Direction.TOP_TO_BOTTOM; + break; + case R.id.left_to_right: + direction = LinearSort.Direction.LEFT_TO_RIGHT; + break; + case R.id.right_to_left: + direction = LinearSort.Direction.RIGHT_TO_LEFT; + break; + } + resetChildViewsAndStartSort(); + } + }); + + // set default corner + corner = CorneredSort.Corner.TOP_LEFT; + corneredRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { + switch (checkedId) { + case R.id.top_left: + corner = CorneredSort.Corner.TOP_LEFT; + break; + case R.id.top_right: + corner = CorneredSort.Corner.TOP_RIGHT; + break; + case R.id.bottom_left: + corner = CorneredSort.Corner.BOTTOM_LEFT; + break; + case R.id.bottom_right: + corner = CorneredSort.Corner.BOTTOM_RIGHT; + break; + } + resetChildViewsAndStartSort(); + } + }); + + linearReversed.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + resetChildViewsAndStartSort(); + } + }); + + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + resetChildViewsAndStartSort(); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + }); + + positionalRadioGroup.setGroupChildChangedListener(this); + resetChildViewsAndStartSort(); + + return rootView; + } + + @Override + public void onResume() { + super.onResume(); + positionalRadioGroup.onResume(); + } + + @Override + public void onRadioGroupChildChanged() { + resetChildViewsAndStartSort(); + } + + + private void resetChildViewsAndStartSort() { + if (spruceAnimator != null) { + spruceAnimator.cancel(); + } + for (View view : children) { + view.setAlpha(0); + } + setupSort(); + } + + private void setupSort() { + SortFunction sortFunction; + switch (sortDropDown.getSelectedItemPosition()) { + case DEFAULT_SORT: + sortFunction = new DefaultSort(seekBar.getProgress()); + codeSample.setText(String.format(getResources().getString(R.string.default_sort_code), seekBar.getProgress())); + break; + case CORNERED_SORT: + sortFunction = new CorneredSort(seekBar.getProgress(), linearReversed.isChecked(), corner); + codeSample.setText(String.format(getResources().getString(R.string.cornered_sort_code), + seekBar.getProgress(), + String.valueOf(linearReversed.isChecked()), + corner)); + break; + case CONTINUOUS_SORT: + sortFunction = new ContinuousSort(seekBar.getProgress() * /*timePaddingOffset=*/20, + linearReversed.isChecked(), + positionalRadioGroup.getPosition()); + codeSample.setText(String.format(getResources().getString(R.string.continuous_sort_code), + seekBar.getProgress() * /*timePaddingOffset=*/20, + String.valueOf(linearReversed.isChecked()), + positionalRadioGroup.getPosition())); + break; + case CONTINUOUS_WEIGHTED_SORT: + sortFunction = new ContinuousWeightedSort(seekBar.getProgress() * /*timePaddingOffset=*/20, + linearReversed.isChecked(), + positionalRadioGroup.getPosition(), + horizontalWeight, + verticalWeight); + codeSample.setText(String.format(getResources().getString(R.string.continuous_weighted_sort_code), + seekBar.getProgress() * /*timePaddingOffset=*/20, + String.valueOf(linearReversed.isChecked()), + positionalRadioGroup.getPosition(), + String.valueOf(horizontalWeight), + String.valueOf(verticalWeight))); + break; + case INLINE_SORT: + sortFunction = new InlineSort(seekBar.getProgress(), linearReversed.isChecked(), corner); + codeSample.setText(String.format(getResources().getString(R.string.inline_sort_code), + seekBar.getProgress(), + String.valueOf(linearReversed.isChecked()), + corner)); + break; + case LINEAR_SORT: + sortFunction = new LinearSort(seekBar.getProgress(), linearReversed.isChecked(), direction); + codeSample.setText(String.format(getResources().getString(R.string.linear_sort_code), + seekBar.getProgress(), + String.valueOf(linearReversed.isChecked()), + direction)); + break; + case RADIAL_SORT: + sortFunction = new RadialSort(seekBar.getProgress(), linearReversed.isChecked(), positionalRadioGroup.getPosition()); + codeSample.setText(String.format(getResources().getString(R.string.radial_sort_code), seekBar.getProgress(), + String.valueOf(linearReversed.isChecked()), + positionalRadioGroup.getPosition())); + break; + case RANDOM_SORT: + sortFunction = new RandomSort(seekBar.getProgress()); + codeSample.setText(String.format(getResources().getString(R.string.random_sort_code), seekBar.getProgress())); + break; + default: + sortFunction = new DefaultSort(seekBar.getProgress()); + codeSample.setText(String.format(getResources().getString(R.string.default_sort_code), seekBar.getProgress())); + break; + } + + if (sortDropDown.getSelectedItemPosition() == CONTINUOUS_SORT || + sortDropDown.getSelectedItemPosition() == CONTINUOUS_WEIGHTED_SORT) { + animationEndText.setText(R.string.animation_end_longer_duration); + seekBarTitle.setText(R.string.duration); + } else { + animationEndText.setText(R.string.animation_end_duration); + seekBarTitle.setText(R.string.delay); + } + + spruceAnimator = new Spruce.SpruceBuilder(parent).sortWith(sortFunction) + .animateWith(animators) + .start(); + + } + +} diff --git a/app/src/main/java/com/willowtreeapps/spurceexampleapp/fragments/ViewFragment.java b/app/src/main/java/com/willowtreeapps/spurceexampleapp/fragments/ViewFragment.java index 51a948b..75d96b6 100644 --- a/app/src/main/java/com/willowtreeapps/spurceexampleapp/fragments/ViewFragment.java +++ b/app/src/main/java/com/willowtreeapps/spurceexampleapp/fragments/ViewFragment.java @@ -22,10 +22,9 @@ package com.willowtreeapps.spurceexampleapp.fragments; -import android.animation.Animator; +import android.content.Context; import android.content.res.Resources; import android.os.Bundle; -import android.support.annotation.IdRes; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.content.ContextCompat; @@ -34,67 +33,20 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.EditText; import android.widget.GridLayout; -import android.widget.LinearLayout; -import android.widget.RadioGroup; -import android.widget.SeekBar; -import android.widget.Spinner; -import android.widget.TextView; -import com.willowtreeapps.spruce.Spruce; -import com.willowtreeapps.spruce.animation.DefaultAnimations; -import com.willowtreeapps.spruce.sort.ContinuousSort; -import com.willowtreeapps.spruce.sort.ContinuousWeightedSort; -import com.willowtreeapps.spruce.sort.CorneredSort; -import com.willowtreeapps.spruce.sort.DefaultSort; -import com.willowtreeapps.spruce.sort.InlineSort; -import com.willowtreeapps.spruce.sort.LinearSort; -import com.willowtreeapps.spruce.sort.RadialSort; -import com.willowtreeapps.spruce.sort.RandomSort; -import com.willowtreeapps.spruce.sort.SortFunction; import com.willowtreeapps.spurceexampleapp.R; -import com.willowtreeapps.spurceexampleapp.widgets.RadioGroupGridLayout; import java.util.ArrayList; import java.util.List; -public class ViewFragment extends Fragment implements RadioGroupGridLayout.OnChangedListener { +public class ViewFragment extends Fragment { - private static final int DEFAULT_SORT = 0; - private static final int CORNERED_SORT = 1; - private static final int CONTINUOUS_SORT = 2; - private static final int CONTINUOUS_WEIGHTED_SORT = 3; - private static final int INLINE_SORT = 4; - private static final int LINEAR_SORT = 5; - private static final int RADIAL_SORT = 6; - private static final int RANDOM_SORT = 7; + OnParentAndChildCreationListener listener; - private Animator spruceAnimator; private GridLayout parent; - private SeekBar seekBar; - private Spinner sortDropDown; - private RadioGroup linearRadioGroup; - private RadioGroup corneredRadioGroup; - private RadioGroupGridLayout positionalRadioGroup; - private double verticalWeight; - private double horizontalWeight; - private CheckBox linearReversed; - private LinearLayout verticalWeightLayout; - private LinearLayout horizontalWeightLayout; - private TextView animationEndText; - private TextView seekBarTitle; - private EditText codeSample; - private List children = new ArrayList<>(); - private Animator[] animators; - private LinearSort.Direction direction; - private CorneredSort.Corner corner; public static ViewFragment newInstance(){ return new ViewFragment(); @@ -103,20 +55,9 @@ public static ViewFragment newInstance(){ @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) { - parent = (GridLayout) container.findViewById(R.id.view_group_to_animate); - linearRadioGroup = (RadioGroup) container.findViewById(R.id.directional_radio_group); - corneredRadioGroup = (RadioGroup) container.findViewById(R.id.cornered_radio_group); - positionalRadioGroup = (RadioGroupGridLayout) container.findViewById(R.id.positional_radio_group); - RadioGroup verticalWeightedRadioGroup = (RadioGroup) container.findViewById(R.id.vertical_weighted_radio_group); - RadioGroup horizontalWeightedRadioGroup = (RadioGroup) container.findViewById(R.id.horizontal_weighted_radio_group); - verticalWeightLayout = (LinearLayout) container.findViewById(R.id.vertical_weight); - horizontalWeightLayout = (LinearLayout) container.findViewById(R.id.horizontal_weight); - linearReversed = (CheckBox) container.findViewById(R.id.linear_reversed); - seekBar = (SeekBar) container.findViewById(R.id.animation_seek); - sortDropDown = (Spinner) container.findViewById(R.id.sort_selection); - animationEndText = (TextView) container.findViewById(R.id.animation_end); - seekBarTitle = (TextView) container.findViewById(R.id.seek_bar_title); - codeSample = (EditText) container.findViewById(R.id.code_sample); + ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.view_fragment, container, false); + parent = (GridLayout) rootView.findViewById(R.id.view_group_to_animate); + final int CHILD_VIEW_COUNT = parent.getColumnCount() * parent.getRowCount(); for (int i = 0; i < CHILD_VIEW_COUNT; i++) { @@ -132,8 +73,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, @Nullable public void onGlobalLayout() { Resources res = getResources(); int tileMargins = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, res.getDisplayMetrics())); - final int childWidth = Math.round(parent.getWidth() / parent.getColumnCount() - parent.getColumnCount() * 2); - final int childHeight = Math.round(parent.getHeight() / parent.getRowCount() - parent.getColumnCount() * 2); + final int childWidth = parent.getWidth() / parent.getColumnCount() - (tileMargins * 2); + final int childHeight = parent.getHeight() / parent.getRowCount() - (tileMargins * 2); for (int i = 0; i < parent.getChildCount(); i++) { View childView = parent.getChildAt(i); @@ -147,299 +88,24 @@ public void onGlobalLayout() { } }); - animators = new Animator[] { - DefaultAnimations.shrinkAnimator(parent, /*duration=*/800), - DefaultAnimations.fadeInAnimator(parent, /*duration=*/800) - }; - - View.OnClickListener click = new View.OnClickListener() { - @Override - public void onClick(View v) { - resetChildViewsAndStartSort(); - } - }; - container.setOnClickListener(click); - parent.setOnClickListener(click); - - ArrayAdapter adapter = ArrayAdapter.createFromResource(getContext(), - R.array.sort_functions, - R.layout.spinner_item); - adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item); - sortDropDown.setAdapter(adapter); - sortDropDown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - switch (position) { - case CORNERED_SORT: - case INLINE_SORT: - linearRadioGroup.setVisibility(View.GONE); - linearReversed.setVisibility(View.VISIBLE); - positionalRadioGroup.setVisibility(View.GONE); - verticalWeightLayout.setVisibility(View.GONE); - horizontalWeightLayout.setVisibility(View.GONE); - corneredRadioGroup.setVisibility(View.VISIBLE); - break; - case LINEAR_SORT: - linearRadioGroup.setVisibility(View.VISIBLE); - linearReversed.setVisibility(View.VISIBLE); - positionalRadioGroup.setVisibility(View.GONE); - verticalWeightLayout.setVisibility(View.GONE); - horizontalWeightLayout.setVisibility(View.GONE); - corneredRadioGroup.setVisibility(View.GONE); - break; - case CONTINUOUS_SORT: - case RADIAL_SORT: - positionalRadioGroup.setVisibility(View.VISIBLE); - verticalWeightLayout.setVisibility(View.GONE); - horizontalWeightLayout.setVisibility(View.GONE); - linearReversed.setVisibility(View.VISIBLE); - linearRadioGroup.setVisibility(View.GONE); - corneredRadioGroup.setVisibility(View.GONE); - break; - case CONTINUOUS_WEIGHTED_SORT: - positionalRadioGroup.setVisibility(View.VISIBLE); - verticalWeightLayout.setVisibility(View.VISIBLE); - horizontalWeightLayout.setVisibility(View.VISIBLE); - linearReversed.setVisibility(View.VISIBLE); - linearRadioGroup.setVisibility(View.GONE); - corneredRadioGroup.setVisibility(View.GONE); - break; - default: - linearReversed.setVisibility(View.GONE); - positionalRadioGroup.setVisibility(View.GONE); - verticalWeightLayout.setVisibility(View.GONE); - horizontalWeightLayout.setVisibility(View.GONE); - linearRadioGroup.setVisibility(View.GONE); - corneredRadioGroup.setVisibility(View.GONE); - break; - } - resetChildViewsAndStartSort(); - } - - @Override - public void onNothingSelected(AdapterView parent) { - - } - }); + listener.onParentAndChildrenPrepared(parent, children); - // set default vertical weight - verticalWeight = ContinuousWeightedSort.MEDIUM_WEIGHT; - verticalWeightedRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { - switch (checkedId) { - case R.id.vertical_light: - verticalWeight = ContinuousWeightedSort.LIGHT_WEIGHT; - break; - case R.id.vertical_medium: - verticalWeight = ContinuousWeightedSort.MEDIUM_WEIGHT; - break; - case R.id.vertical_heavy: - verticalWeight = ContinuousWeightedSort.HEAVY_WEIGHT; - break; - } - resetChildViewsAndStartSort(); - } - }); - - // set default horizontal weight - horizontalWeight = ContinuousWeightedSort.MEDIUM_WEIGHT; - horizontalWeightedRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { - switch (checkedId) { - case R.id.horizontal_light: - horizontalWeight = ContinuousWeightedSort.LIGHT_WEIGHT; - break; - case R.id.horizontal_medium: - horizontalWeight = ContinuousWeightedSort.MEDIUM_WEIGHT; - break; - case R.id.horizontal_heavy: - horizontalWeight = ContinuousWeightedSort.HEAVY_WEIGHT; - break; - } - resetChildViewsAndStartSort(); - } - }); - - // set default direction - direction = LinearSort.Direction.BOTTOM_TO_TOP; - linearRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { - switch (checkedId) - { - case R.id.bottom_to_top: - direction = LinearSort.Direction.BOTTOM_TO_TOP; - break; - case R.id.top_to_bottom: - direction = LinearSort.Direction.TOP_TO_BOTTOM; - break; - case R.id.left_to_right: - direction = LinearSort.Direction.LEFT_TO_RIGHT; - break; - case R.id.right_to_left: - direction = LinearSort.Direction.RIGHT_TO_LEFT; - break; - } - resetChildViewsAndStartSort(); - } - }); - - // set default corner - corner = CorneredSort.Corner.TOP_LEFT; - corneredRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { - switch (checkedId) - { - case R.id.top_left: - corner = CorneredSort.Corner.TOP_LEFT; - break; - case R.id.top_right: - corner = CorneredSort.Corner.TOP_RIGHT; - break; - case R.id.bottom_left: - corner = CorneredSort.Corner.BOTTOM_LEFT; - break; - case R.id.bottom_right: - corner = CorneredSort.Corner.BOTTOM_RIGHT; - break; - } - resetChildViewsAndStartSort(); - } - }); - - linearReversed.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - resetChildViewsAndStartSort(); - } - }); - - seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - resetChildViewsAndStartSort(); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - - } - }); - - positionalRadioGroup.setGroupChildChangedListener(this); - resetChildViewsAndStartSort(); - - return super.onCreateView(inflater, container, savedInstanceState); + return rootView; } @Override - public void onResume() { - super.onResume(); - positionalRadioGroup.onResume(); - } + public void onAttach(Context context) { + super.onAttach(context); - @Override - public void onRadioGroupChildChanged() { - resetChildViewsAndStartSort(); - } - - private void resetChildViewsAndStartSort() { - if (spruceAnimator != null) { - spruceAnimator.cancel(); - } - for (View view : children) { - view.setAlpha(0); + try { + listener = (OnParentAndChildCreationListener) context; + } catch (ClassCastException e) { + throw new ClassCastException(context.toString() + " must implement OnParentAndChildCreationListener"); } - setupSort(); } - private void setupSort() { - SortFunction sortFunction; - switch (sortDropDown.getSelectedItemPosition()) { - case DEFAULT_SORT: - sortFunction = new DefaultSort(seekBar.getProgress()); - codeSample.setText(String.format(getResources().getString(R.string.default_sort_code), seekBar.getProgress())); - break; - case CORNERED_SORT: - sortFunction = new CorneredSort(seekBar.getProgress(), linearReversed.isChecked(), corner); - codeSample.setText(String.format(getResources().getString(R.string.cornered_sort_code), - seekBar.getProgress(), - String.valueOf(linearReversed.isChecked()), - corner)); - break; - case CONTINUOUS_SORT: - sortFunction = new ContinuousSort(seekBar.getProgress() * /*timePaddingOffset=*/20, - linearReversed.isChecked(), - positionalRadioGroup.getPosition()); - codeSample.setText(String.format(getResources().getString(R.string.continuous_sort_code), - seekBar.getProgress() * /*timePaddingOffset=*/20, - String.valueOf(linearReversed.isChecked()), - positionalRadioGroup.getPosition())); - break; - case CONTINUOUS_WEIGHTED_SORT: - sortFunction = new ContinuousWeightedSort(seekBar.getProgress() * /*timePaddingOffset=*/20, - linearReversed.isChecked(), - positionalRadioGroup.getPosition(), - horizontalWeight, - verticalWeight); - codeSample.setText(String.format(getResources().getString(R.string.continuous_weighted_sort_code), - seekBar.getProgress() * /*timePaddingOffset=*/20, - String.valueOf(linearReversed.isChecked()), - positionalRadioGroup.getPosition(), - String.valueOf(horizontalWeight), - String.valueOf(verticalWeight))); - break; - case INLINE_SORT: - sortFunction = new InlineSort(seekBar.getProgress(), linearReversed.isChecked(), corner); - codeSample.setText(String.format(getResources().getString(R.string.inline_sort_code), - seekBar.getProgress(), - String.valueOf(linearReversed.isChecked()), - corner)); - break; - case LINEAR_SORT: - sortFunction = new LinearSort(seekBar.getProgress(), linearReversed.isChecked(), direction); - codeSample.setText(String.format(getResources().getString(R.string.linear_sort_code), - seekBar.getProgress(), - String.valueOf(linearReversed.isChecked()), - direction)); - break; - case RADIAL_SORT: - sortFunction = new RadialSort(seekBar.getProgress(), linearReversed.isChecked(), positionalRadioGroup.getPosition()); - codeSample.setText(String.format(getResources().getString(R.string.radial_sort_code), seekBar.getProgress(), - String.valueOf(linearReversed.isChecked()), - positionalRadioGroup.getPosition())); - break; - case RANDOM_SORT: - sortFunction = new RandomSort(seekBar.getProgress()); - codeSample.setText(String.format(getResources().getString(R.string.random_sort_code), seekBar.getProgress())); - break; - default: - sortFunction = new DefaultSort(seekBar.getProgress()); - codeSample.setText(String.format(getResources().getString(R.string.default_sort_code), seekBar.getProgress())); - break; - } - - if (sortDropDown.getSelectedItemPosition() == CONTINUOUS_SORT || - sortDropDown.getSelectedItemPosition() == CONTINUOUS_WEIGHTED_SORT) { - animationEndText.setText(R.string.animation_end_longer_duration); - seekBarTitle.setText(R.string.duration); - } else { - animationEndText.setText(R.string.animation_end_duration); - seekBarTitle.setText(R.string.delay); - } - - spruceAnimator = new Spruce.SpruceBuilder(parent).sortWith(sortFunction) - .animateWith(animators) - .start(); - + public interface OnParentAndChildCreationListener { + void onParentAndChildrenPrepared(ViewGroup parent, List children); } } \ No newline at end of file diff --git a/app/src/main/java/com/willowtreeapps/spurceexampleapp/pager/VerticalViewPager.java b/app/src/main/java/com/willowtreeapps/spurceexampleapp/pager/VerticalViewPager.java new file mode 100644 index 0000000..4b9afc9 --- /dev/null +++ b/app/src/main/java/com/willowtreeapps/spurceexampleapp/pager/VerticalViewPager.java @@ -0,0 +1,94 @@ +/* + * Spruce + * + * Copyright (c) 2017 WillowTree, Inc. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.willowtreeapps.spurceexampleapp.pager; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +public class VerticalViewPager extends ViewPager { + + public VerticalViewPager(Context context) { + super(context); + init(); + } + + public VerticalViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + private void init() { + setPageTransformer(true, new VerticalPageTransformer()); + setOverScrollMode(OVER_SCROLL_NEVER); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev){ + boolean intercepted = super.onInterceptTouchEvent(swapXY(ev)); + swapXY(ev); + return intercepted; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + return super.onTouchEvent(swapXY(ev)); + } + + private MotionEvent swapXY(MotionEvent ev) { + float width = getWidth(); + float height = getHeight(); + + float newX = (ev.getY() / height) * width; + float newY = (ev.getX() / width) * height; + + ev.setLocation(newX, newY); + + return ev; + } + + private class VerticalPageTransformer implements ViewPager.PageTransformer { + + @Override + public void transformPage(View view, float position) { + + if (position < -1) { + view.setAlpha(0); + + } else if (position <= 1) { + view.setAlpha(1); + + view.setTranslationX(view.getWidth() * -position); + + float yPosition = position * view.getHeight(); + view.setTranslationY(yPosition); + + } else { + view.setAlpha(0); + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_keyboard_arrow_up_24dp.xml b/app/src/main/res/drawable/ic_keyboard_arrow_up_24dp.xml new file mode 100644 index 0000000..7c6aa72 --- /dev/null +++ b/app/src/main/res/drawable/ic_keyboard_arrow_up_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_fragment.xml b/app/src/main/res/layout/activity_fragment.xml deleted file mode 100644 index d0fa366..0000000 --- a/app/src/main/res/layout/activity_fragment.xml +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/continuous_radio_group.xml b/app/src/main/res/layout/continuous_radio_group.xml index 1eaed81..34f2cb2 100644 --- a/app/src/main/res/layout/continuous_radio_group.xml +++ b/app/src/main/res/layout/continuous_radio_group.xml @@ -22,88 +22,95 @@ --> + android:orientation="horizontal"> - + android:visibility="gone" + android:orientation="vertical"> - - - + android:layout_gravity="center" + android:text="@string/vertical"/> - + android:layout_height="wrap_content"> - + - + - + - + - + - - - + android:layout_height="wrap_content" + android:visibility="gone" + android:orientation="vertical"> - + android:layout_gravity="center" + android:text="@string/horizontal"/> - - - + android:layout_height="wrap_content"> + + + + + + + + + + diff --git a/app/src/main/res/layout/controls_fragment.xml b/app/src/main/res/layout/controls_fragment.xml new file mode 100644 index 0000000..acb8801 --- /dev/null +++ b/app/src/main/res/layout/controls_fragment.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/cornered_radio_group.xml b/app/src/main/res/layout/cornered_radio_group.xml index a9bdc44..3d2882b 100644 --- a/app/src/main/res/layout/cornered_radio_group.xml +++ b/app/src/main/res/layout/cornered_radio_group.xml @@ -22,14 +22,13 @@ --> + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/positional_radio_group.xml b/app/src/main/res/layout/positional_radio_group.xml index 370619f..df5bf66 100644 --- a/app/src/main/res/layout/positional_radio_group.xml +++ b/app/src/main/res/layout/positional_radio_group.xml @@ -22,8 +22,8 @@ --> + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cecd216..e6c30ec 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -80,4 +80,5 @@ new LinearSort(%1$d, %2$s, LinearSort.Direction.%3$s); new RadialSort(%1$d, %2$s, RadialSort.Position.%3$s); new RandomSort(%1$d); + Sort Controls