From 05cb65c482ea8bdba62178a2dd1e23935bc4da01 Mon Sep 17 00:00:00 2001 From: wintmain Date: Sat, 27 Sep 2025 23:40:07 +0800 Subject: [PATCH 1/4] [wBasis][feat]Add transition sample Basic transition & for lib --- app-catalog/samples/wBasis/build.gradle | 1 + .../wBasis/activities/SampleActivityBase.java | 48 +++ .../wBasis/view/SlidingTabLayout.java | 310 ++++++++++++++++++ .../wintmain/wBasis/view/SlidingTabStrip.java | 205 ++++++++++++ .../wBasis/src/main/AndroidManifest.xml | 5 + .../transition/BasicTransitionActivity.java | 120 +++++++ .../transition/BasicTransitionFragment.java | 117 +++++++ .../src/main/res-transition/drawable/oval.xml | 20 ++ .../main/res-transition/drawable/tile.9.png | Bin 0 -> 196 bytes .../drawable/transition_ic_launcher.png | Bin 0 -> 5810 bytes .../basic_transition_activity.xml | 73 +++++ .../layout/basic_transition_activity.xml | 65 ++++ .../layout/fragment_basic_transition.xml | 82 +++++ .../src/main/res-transition/layout/scene1.xml | 44 +++ .../src/main/res-transition/layout/scene2.xml | 46 +++ .../src/main/res-transition/layout/scene3.xml | 54 +++ .../src/main/res-transition/menu/main.xml | 23 ++ .../changebounds_fadein_together.xml | 24 ++ .../transition/scene3_transition_manager.xml | 21 ++ .../values-sw600dp/template-dimens.xml | 24 ++ .../values-sw600dp/template-styles.xml | 25 ++ .../src/main/res-transition/values/dimens.xml | 36 ++ .../main/res-transition/values/strings.xml | 40 +++ 23 files changed, 1383 insertions(+) create mode 100644 app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/activities/SampleActivityBase.java create mode 100644 app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/view/SlidingTabLayout.java create mode 100644 app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/view/SlidingTabStrip.java create mode 100644 app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/BasicTransitionActivity.java create mode 100644 app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/BasicTransitionFragment.java create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/drawable/oval.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/drawable/tile.9.png create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/drawable/transition_ic_launcher.png create mode 100755 app-catalog/samples/wBasis/src/main/res-transition/layout-w720dp/basic_transition_activity.xml create mode 100755 app-catalog/samples/wBasis/src/main/res-transition/layout/basic_transition_activity.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/layout/fragment_basic_transition.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/layout/scene1.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/layout/scene2.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/layout/scene3.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/menu/main.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/transition/changebounds_fadein_together.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/transition/scene3_transition_manager.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/values-sw600dp/template-dimens.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/values-sw600dp/template-styles.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/values/dimens.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/values/strings.xml diff --git a/app-catalog/samples/wBasis/build.gradle b/app-catalog/samples/wBasis/build.gradle index 3860e29..9ea9647 100644 --- a/app-catalog/samples/wBasis/build.gradle +++ b/app-catalog/samples/wBasis/build.gradle @@ -9,6 +9,7 @@ android { res.srcDirs( 'src/main/res', 'src/main/res-ext', + 'src/main/res-transition', ) } } diff --git a/app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/activities/SampleActivityBase.java b/app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/activities/SampleActivityBase.java new file mode 100644 index 0000000..d199eac --- /dev/null +++ b/app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/activities/SampleActivityBase.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023-2025 wintmain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lib.wintmain.wBasis.activities; + +import android.os.Bundle; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; +import lib.wintmain.wBasis.logger.Log; +import lib.wintmain.wBasis.logger.LogWrapper; + +public class SampleActivityBase extends FragmentActivity { + public final static String TAG = SampleActivityBase.class.getSimpleName(); + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + protected void onStart() { + super.onStart(); + initializeLogging(); + } + + /** Set up targets to receive log data */ + public void initializeLogging() { + // Using Log, front-end to the logging chain, emulates android.util.log method signatures. + // Wraps Android's native log framework + LogWrapper logWrapper = new LogWrapper(); + Log.setLogNode(logWrapper); + + Log.i(TAG, "Ready"); + } +} diff --git a/app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/view/SlidingTabLayout.java b/app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/view/SlidingTabLayout.java new file mode 100644 index 0000000..c849b67 --- /dev/null +++ b/app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/view/SlidingTabLayout.java @@ -0,0 +1,310 @@ +/* + * Copyright 2023-2025 wintmain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lib.wintmain.wBasis.view; + +import android.content.Context; +import android.graphics.Typeface; +import android.os.Build; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.HorizontalScrollView; +import android.widget.TextView; +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +/** + * To be used with ViewPager to provide a tab indicator component which give constant feedback as to + * the user's scroll progress. + *

+ * To use the component, simply add it to your view hierarchy. Then in your + * {@link android.app.Activity} or {@link Fragment} call + * {@link #setViewPager(ViewPager)} providing it the ViewPager this layout is being used for. + *

+ * The colors can be customized in two ways. The first and simplest is to provide an array of colors + * via {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)}. The + * alternative is via the {@link TabColorizer} interface which provides you complete control over + * which color is used for any individual position. + *

+ * The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)}, + * providing the layout ID of your custom layout. + */ +public class SlidingTabLayout extends HorizontalScrollView { + /** + * Allows complete control over the colors drawn in the tab layout. Set with + * {@link #setCustomTabColorizer(TabColorizer)}. + */ + public interface TabColorizer { + + /** + * @return return the color of the indicator used when {@code position} is selected. + */ + int getIndicatorColor(int position); + + /** + * @return return the color of the divider drawn to the right of {@code position}. + */ + int getDividerColor(int position); + + } + + private static final int TITLE_OFFSET_DIPS = 24; + private static final int TAB_VIEW_PADDING_DIPS = 16; + private static final int TAB_VIEW_TEXT_SIZE_SP = 12; + + private final int mTitleOffset; + private final SlidingTabStrip mTabStrip; + + private int mTabViewLayoutId; + private int mTabViewTextViewId; + + private ViewPager mViewPager; + private ViewPager.OnPageChangeListener mViewPagerPageChangeListener; + + public SlidingTabLayout(Context context) { + this(context, null); + } + + public SlidingTabLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + // Disable the Scroll Bar & Make sure that the Tab Strips fills this View + setHorizontalScrollBarEnabled(false); + setFillViewport(true); + + mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density); + + mTabStrip = new SlidingTabStrip(context); + addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + } + + /** + * Set the custom {@link TabColorizer} to be used. + * + * If you only require simple custmisation then you can use + * {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve + * similar effects. + */ + public void setCustomTabColorizer(TabColorizer tabColorizer) { + mTabStrip.setCustomTabColorizer(tabColorizer); + } + + /** + * Sets the colors to be used for indicating the selected tab. These colors are treated as a + * circular array. Providing one color will mean that all tabs are indicated with the same color. + */ + public void setSelectedIndicatorColors(int... colors) { + mTabStrip.setSelectedIndicatorColors(colors); + } + + /** + * Sets the colors to be used for tab dividers. These colors are treated as a circular array. + * Providing one color will mean that all tabs are indicated with the same color. + */ + public void setDividerColors(int... colors) { + mTabStrip.setDividerColors(colors); + } + + /** + * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SlidingTabLayout} you are + * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so + * that the layout can update it's scroll position correctly. + * + * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener) + */ + public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { + mViewPagerPageChangeListener = listener; + } + + /** + * Set the custom layout to be inflated for the tab views. + * + * @param layoutResId Layout id to be inflated + * @param textViewId id of the {@link TextView} in the inflated view + */ + public void setCustomTabView(int layoutResId, int textViewId) { + mTabViewLayoutId = layoutResId; + mTabViewTextViewId = textViewId; + } + + /** + * Sets the associated view pager. Note that the assumption here is that the pager content + * (number of tabs and tab titles) does not change after this call has been made. + */ + public void setViewPager(ViewPager viewPager) { + mTabStrip.removeAllViews(); + + mViewPager = viewPager; + if (viewPager != null) { + viewPager.setOnPageChangeListener(new InternalViewPagerListener()); + populateTabStrip(); + } + } + + /** + * Create a default view to be used for tabs. This is called if a custom tab view is not set via + * {@link #setCustomTabView(int, int)}. + */ + protected TextView createDefaultTabView(Context context) { + TextView textView = new TextView(context); + textView.setGravity(Gravity.CENTER); + textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP); + textView.setTypeface(Typeface.DEFAULT_BOLD); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + // If we're running on Honeycomb or newer, then we can use the Theme's + // selectableItemBackground to ensure that the View has a pressed state + TypedValue outValue = new TypedValue(); + getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, + outValue, true); + textView.setBackgroundResource(outValue.resourceId); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + // If we're running on ICS or newer, enable all-caps to match the Action Bar tab style + textView.setAllCaps(true); + } + + int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density); + textView.setPadding(padding, padding, padding, padding); + + return textView; + } + + private void populateTabStrip() { + final PagerAdapter adapter = mViewPager.getAdapter(); + final View.OnClickListener tabClickListener = new TabClickListener(); + + for (int i = 0; i < adapter.getCount(); i++) { + View tabView = null; + TextView tabTitleView = null; + + if (mTabViewLayoutId != 0) { + // If there is a custom tab view layout id set, try and inflate it + tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip, + false); + tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId); + } + + if (tabView == null) { + tabView = createDefaultTabView(getContext()); + } + + if (tabTitleView == null && TextView.class.isInstance(tabView)) { + tabTitleView = (TextView) tabView; + } + + tabTitleView.setText(adapter.getPageTitle(i)); + tabView.setOnClickListener(tabClickListener); + + mTabStrip.addView(tabView); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + if (mViewPager != null) { + scrollToTab(mViewPager.getCurrentItem(), 0); + } + } + + private void scrollToTab(int tabIndex, int positionOffset) { + final int tabStripChildCount = mTabStrip.getChildCount(); + if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) { + return; + } + + View selectedChild = mTabStrip.getChildAt(tabIndex); + if (selectedChild != null) { + int targetScrollX = selectedChild.getLeft() + positionOffset; + + if (tabIndex > 0 || positionOffset > 0) { + // If we're not at the first child and are mid-scroll, make sure we obey the offset + targetScrollX -= mTitleOffset; + } + + scrollTo(targetScrollX, 0); + } + } + + private class InternalViewPagerListener implements ViewPager.OnPageChangeListener { + private int mScrollState; + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + int tabStripChildCount = mTabStrip.getChildCount(); + if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) { + return; + } + + mTabStrip.onViewPagerPageChanged(position, positionOffset); + + View selectedTitle = mTabStrip.getChildAt(position); + int extraOffset = (selectedTitle != null) + ? (int) (positionOffset * selectedTitle.getWidth()) + : 0; + scrollToTab(position, extraOffset); + + if (mViewPagerPageChangeListener != null) { + mViewPagerPageChangeListener.onPageScrolled(position, positionOffset, + positionOffsetPixels); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + mScrollState = state; + + if (mViewPagerPageChangeListener != null) { + mViewPagerPageChangeListener.onPageScrollStateChanged(state); + } + } + + @Override + public void onPageSelected(int position) { + if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { + mTabStrip.onViewPagerPageChanged(position, 0f); + scrollToTab(position, 0); + } + + if (mViewPagerPageChangeListener != null) { + mViewPagerPageChangeListener.onPageSelected(position); + } + } + } + + private class TabClickListener implements View.OnClickListener { + @Override + public void onClick(View v) { + for (int i = 0; i < mTabStrip.getChildCount(); i++) { + if (v == mTabStrip.getChildAt(i)) { + mViewPager.setCurrentItem(i); + return; + } + } + } + } +} diff --git a/app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/view/SlidingTabStrip.java b/app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/view/SlidingTabStrip.java new file mode 100644 index 0000000..da3be39 --- /dev/null +++ b/app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/view/SlidingTabStrip.java @@ -0,0 +1,205 @@ +/* + * Copyright 2023-2025 wintmain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lib.wintmain.wBasis.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.View; +import android.widget.LinearLayout; +import androidx.annotation.Nullable; + +public class SlidingTabStrip extends LinearLayout { + private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 2; + private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26; + private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 8; + private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5; + private static final int DEFAULT_DIVIDER_THICKNESS_DIPS = 1; + private static final byte DEFAULT_DIVIDER_COLOR_ALPHA = 0x20; + private static final float DEFAULT_DIVIDER_HEIGHT = 0.5f; + + private SlidingTabLayout.TabColorizer mCustomTabColorizer; + private final SimpleTabColorizer mDefaultTabColorizer; + + private final int mBottomBorderThickness; + private final Paint mBottomBorderPaint; + + private final int mSelectedIndicatorThickness; + private final Paint mSelectedIndicatorPaint; + + private final Paint mDividerPaint; + private final float mDividerHeight; + + private int mSelectedPosition; + private float mSelectionOffset; + + public SlidingTabStrip(Context context) { + this(context, null); + } + + public SlidingTabStrip(Context context, + @Nullable AttributeSet attrs) { + super(context, attrs); + setWillNotDraw(false); + + final float density = getResources().getDisplayMetrics().density; + + TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(android.R.attr.colorForeground, outValue, true); + final int themeForegroundColor = outValue.data; + + int mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor, + DEFAULT_BOTTOM_BORDER_COLOR_ALPHA); + + mDefaultTabColorizer = new SimpleTabColorizer(); + mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR); + mDefaultTabColorizer.setDividerColors(setColorAlpha(themeForegroundColor, + DEFAULT_DIVIDER_COLOR_ALPHA)); + + mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density); + mBottomBorderPaint = new Paint(); + mBottomBorderPaint.setColor(mDefaultBottomBorderColor); + + mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density); + mSelectedIndicatorPaint = new Paint(); + + mDividerHeight = DEFAULT_DIVIDER_HEIGHT; + mDividerPaint = new Paint(); + mDividerPaint.setStrokeWidth((int) (DEFAULT_DIVIDER_THICKNESS_DIPS * density)); + } + + /** + * Set the alpha value of the {@code color} to be the given {@code alpha} value. + */ + private static int setColorAlpha(int color, byte alpha) { + return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); + } + + void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) { + mCustomTabColorizer = customTabColorizer; + invalidate(); + } + + void setSelectedIndicatorColors(int... colors) { + // Make sure that the custom colorizer is removed + mCustomTabColorizer = null; + mDefaultTabColorizer.setIndicatorColors(colors); + invalidate(); + } + + void setDividerColors(int... colors) { + // Make sure that the custom colorizer is removed + mCustomTabColorizer = null; + mDefaultTabColorizer.setDividerColors(colors); + invalidate(); + } + + void onViewPagerPageChanged(int position, float positionOffset) { + mSelectedPosition = position; + mSelectionOffset = positionOffset; + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + final int height = getHeight(); + final int childCount = getChildCount(); + final int dividerHeightPx = (int) (Math.min(Math.max(0f, mDividerHeight), 1f) * height); + final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null + ? mCustomTabColorizer + : mDefaultTabColorizer; + + // Thick colored underline below the current selection + if (childCount > 0) { + View selectedTitle = getChildAt(mSelectedPosition); + int left = selectedTitle.getLeft(); + int right = selectedTitle.getRight(); + int color = tabColorizer.getIndicatorColor(mSelectedPosition); + + if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) { + int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1); + if (color != nextColor) { + color = blendColors(nextColor, color, mSelectionOffset); + } + + // Draw the selection partway between the tabs + View nextTitle = getChildAt(mSelectedPosition + 1); + left = (int) (mSelectionOffset * nextTitle.getLeft() + + (1.0f - mSelectionOffset) * left); + right = (int) (mSelectionOffset * nextTitle.getRight() + + (1.0f - mSelectionOffset) * right); + } + + mSelectedIndicatorPaint.setColor(color); + + canvas.drawRect(left, height - mSelectedIndicatorThickness, right, + height, mSelectedIndicatorPaint); + } + + // Thin underline along the entire bottom edge + canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint); + + // Vertical separators between the titles + int separatorTop = (height - dividerHeightPx) / 2; + for (int i = 0; i < childCount - 1; i++) { + View child = getChildAt(i); + mDividerPaint.setColor(tabColorizer.getDividerColor(i)); + canvas.drawLine(child.getRight(), separatorTop, child.getRight(), + separatorTop + dividerHeightPx, mDividerPaint); + } + } + + /** + * Blend {@code color1} and {@code color2} using the given ratio. + * + * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, + * 0.0 will return {@code color2}. + */ + private static int blendColors(int color1, int color2, float ratio) { + final float inverseRation = 1f - ratio; + float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation); + float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation); + float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation); + return Color.rgb((int) r, (int) g, (int) b); + } + + private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer { + private int[] mIndicatorColors; + private int[] mDividerColors; + + @Override + public final int getIndicatorColor(int position) { + return mIndicatorColors[position % mIndicatorColors.length]; + } + + @Override + public final int getDividerColor(int position) { + return mDividerColors[position % mDividerColors.length]; + } + + void setIndicatorColors(int... colors) { + mIndicatorColors = colors; + } + + void setDividerColors(int... colors) { + mDividerColors = colors; + } + } +} diff --git a/app-catalog/samples/wBasis/src/main/AndroidManifest.xml b/app-catalog/samples/wBasis/src/main/AndroidManifest.xml index 14a79b4..3978f68 100644 --- a/app-catalog/samples/wBasis/src/main/AndroidManifest.xml +++ b/app-catalog/samples/wBasis/src/main/AndroidManifest.xml @@ -368,6 +368,11 @@ android:name=".webview.CustomActionWebViewActivity" android:exported="true" android:theme="@style/Theme.AppCompat.DayNight" /> + + \ No newline at end of file diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/BasicTransitionActivity.java b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/BasicTransitionActivity.java new file mode 100644 index 0000000..54f2d41 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/BasicTransitionActivity.java @@ -0,0 +1,120 @@ +/* + * Copyright 2023-2025 wintmain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.wintmain.wBasis.transition; + +import android.app.Fragment; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.ViewAnimator; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.FragmentTransaction; +import com.google.android.catalog.framework.annotations.Sample; +import com.wintmain.wBasis.R; +import lib.wintmain.wBasis.logger.Log; +import lib.wintmain.wBasis.logger.LogFragment; +import lib.wintmain.wBasis.logger.LogWrapper; +import lib.wintmain.wBasis.logger.MessageOnlyLogFilter; + +/** + * A simple launcher activity containing a summary sample description, sample log and a custom + * {@link Fragment} which can display a view. + *

+ * For devices with displays with a width of 720dp or greater, the sample log is always visible, + * on other devices it's visibility is controlled by an item on the Action Bar. + */ +@Sample(name = "BasicTransition", + description = "基础的变化", + tags = {"android-samples", "animation-samples"} +) +public class BasicTransitionActivity extends AppCompatActivity { + + public static final String TAG = "MainActivity"; + + // Whether the Log Fragment is currently shown + private boolean mLogShown; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.basic_transition_activity); + + if (savedInstanceState == null) { + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + BasicTransitionFragment fragment = new BasicTransitionFragment(); + transaction.replace(R.id.sample_content_fragment, fragment); + transaction.commit(); + } + } + + @Override + protected void onStart() { + super.onStart(); + initializeLogging(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.main, menu); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + MenuItem logToggle = menu.findItem(R.id.menu_toggle_log); + logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator); + logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log); + + return super.onPrepareOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.menu_toggle_log) { + mLogShown = !mLogShown; + ViewAnimator output = (ViewAnimator) findViewById(R.id.sample_output); + if (mLogShown) { + output.setDisplayedChild(1); + } else { + output.setDisplayedChild(0); + } + supportInvalidateOptionsMenu(); + return true; + } + return super.onOptionsItemSelected(item); + } + + // Set up targets to receive log data + /** Create a chain of targets that will receive log data */ + public void initializeLogging() { + // Wraps Android's native log framework. + LogWrapper logWrapper = new LogWrapper(); + // Using Log, front-end to the logging chain, emulates android.util.log method signatures. + Log.setLogNode(logWrapper); + + // Filter strips out everything except the message text. + MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter(); + logWrapper.setNext(msgFilter); + + // On screen logging via a fragment with a TextView. + LogFragment logFragment = (LogFragment) getSupportFragmentManager() + .findFragmentById(R.id.log_fragment); + msgFilter.setNext(logFragment.getLogView()); + + Log.i(TAG, "Ready"); + } +} diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/BasicTransitionFragment.java b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/BasicTransitionFragment.java new file mode 100644 index 0000000..c588756 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/BasicTransitionFragment.java @@ -0,0 +1,117 @@ +/* + * Copyright 2023-2025 wintmain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.wintmain.wBasis.transition; + +import android.os.Bundle; +import android.transition.Scene; +import android.transition.TransitionInflater; +import android.transition.TransitionManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RadioGroup; +import androidx.fragment.app.Fragment; +import com.wintmain.wBasis.R; +import lib.wintmain.wBasis.logger.Log; + +public class BasicTransitionFragment extends Fragment + implements RadioGroup.OnCheckedChangeListener { + + // We transition between these Scenes + private Scene mScene1; + private Scene mScene2; + private Scene mScene3; + + /** A custom TransitionManager */ + private TransitionManager mTransitionManagerForScene3; + + /** Transitions take place in this ViewGroup. We retain this for the dynamic transition on scene 4. */ + private ViewGroup mSceneRoot; + + public static BasicTransitionFragment newInstance() { + return new BasicTransitionFragment(); + } + + public BasicTransitionFragment() { + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_basic_transition, container, false); + assert view != null; + RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.select_scene); + radioGroup.setOnCheckedChangeListener(this); + mSceneRoot = (ViewGroup) view.findViewById(R.id.scene_root); + + // BEGIN_INCLUDE(instantiation_from_view) + // A Scene can be instantiated from a live view hierarchy. + mScene1 = new Scene(mSceneRoot, (ViewGroup) mSceneRoot.findViewById(R.id.container)); + // END_INCLUDE(instantiation_from_view) + + // BEGIN_INCLUDE(instantiation_from_resource) + // You can also inflate a generate a Scene from a layout resource file. + mScene2 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene2, getActivity()); + // END_INCLUDE(instantiation_from_resource) + + // Another scene from a layout resource file. + mScene3 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene3, getActivity()); + + // BEGIN_INCLUDE(custom_transition_manager) + // We create a custom TransitionManager for Scene 3, in which ChangeBounds and Fade + // take place at the same time. + mTransitionManagerForScene3 = TransitionInflater.from(getActivity()) + .inflateTransitionManager(R.transition.scene3_transition_manager, mSceneRoot); + // END_INCLUDE(custom_transition_manager) + + return view; + } + + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + if (checkedId == R.id.select_scene_1) { + // BEGIN_INCLUDE(transition_simple) + // You can start an automatic transition with TransitionManager.go(). + TransitionManager.go(mScene1); + Log.d(BasicTransitionActivity.TAG, "select 1"); + // END_INCLUDE(transition_simple) + } else if (checkedId == R.id.select_scene_2) { + TransitionManager.go(mScene2); + Log.d(BasicTransitionActivity.TAG, "select 2"); + } else if (checkedId == R.id.select_scene_3) { + // BEGIN_INCLUDE(transition_custom) + // You can also start a transition with a custom TransitionManager. + mTransitionManagerForScene3.transitionTo(mScene3); + Log.d(BasicTransitionActivity.TAG, "select 3"); + // END_INCLUDE(transition_custom) + } else if (checkedId == R.id.select_scene_4) { + // BEGIN_INCLUDE(transition_dynamic) + // Alternatively, transition can be invoked dynamically without a Scene. + // For this, we first call TransitionManager.beginDelayedTransition(). + TransitionManager.beginDelayedTransition(mSceneRoot); + // Then, we can just change view properties as usual. + View square = mSceneRoot.findViewById(R.id.transition_square); + ViewGroup.LayoutParams params = square.getLayoutParams(); + int newSize = getResources().getDimensionPixelSize(R.dimen.square_size_expanded); + params.width = newSize; + params.height = newSize; + square.setLayoutParams(params); + Log.d(BasicTransitionActivity.TAG, "select 4"); + // END_INCLUDE(transition_dynamic) + } + } +} diff --git a/app-catalog/samples/wBasis/src/main/res-transition/drawable/oval.xml b/app-catalog/samples/wBasis/src/main/res-transition/drawable/oval.xml new file mode 100644 index 0000000..07f3abd --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/drawable/oval.xml @@ -0,0 +1,20 @@ + + + + + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/drawable/tile.9.png b/app-catalog/samples/wBasis/src/main/res-transition/drawable/tile.9.png new file mode 100644 index 0000000000000000000000000000000000000000..135862883e26eddce2b19db021adf62e10357ad0 GIT binary patch literal 196 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 + + + + + + + + + + + + + + + + + + + + + + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout/basic_transition_activity.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout/basic_transition_activity.xml new file mode 100755 index 0000000..f581afd --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/basic_transition_activity.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout/fragment_basic_transition.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout/fragment_basic_transition.xml new file mode 100644 index 0000000..ff60550 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/fragment_basic_transition.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout/scene1.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout/scene1.xml new file mode 100644 index 0000000..5a0d486 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/scene1.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout/scene2.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout/scene2.xml new file mode 100644 index 0000000..2d80b18 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/scene2.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout/scene3.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout/scene3.xml new file mode 100644 index 0000000..99f7844 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/scene3.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app-catalog/samples/wBasis/src/main/res-transition/menu/main.xml b/app-catalog/samples/wBasis/src/main/res-transition/menu/main.xml new file mode 100644 index 0000000..29c52f8 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/menu/main.xml @@ -0,0 +1,23 @@ + + +

+ + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/transition/changebounds_fadein_together.xml b/app-catalog/samples/wBasis/src/main/res-transition/transition/changebounds_fadein_together.xml new file mode 100644 index 0000000..062e012 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/transition/changebounds_fadein_together.xml @@ -0,0 +1,24 @@ + + + + + + + + + + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/transition/scene3_transition_manager.xml b/app-catalog/samples/wBasis/src/main/res-transition/transition/scene3_transition_manager.xml new file mode 100644 index 0000000..6189d61 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/transition/scene3_transition_manager.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/values-sw600dp/template-dimens.xml b/app-catalog/samples/wBasis/src/main/res-transition/values-sw600dp/template-dimens.xml new file mode 100644 index 0000000..22074a2 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/values-sw600dp/template-dimens.xml @@ -0,0 +1,24 @@ + + + + + + + @dimen/margin_huge + @dimen/margin_medium + + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/values-sw600dp/template-styles.xml b/app-catalog/samples/wBasis/src/main/res-transition/values-sw600dp/template-styles.xml new file mode 100644 index 0000000..03d1974 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/values-sw600dp/template-styles.xml @@ -0,0 +1,25 @@ + + + + + + + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/values/dimens.xml b/app-catalog/samples/wBasis/src/main/res-transition/values/dimens.xml new file mode 100644 index 0000000..6d77398 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/values/dimens.xml @@ -0,0 +1,36 @@ + + + + 16dp + 16dp + 50dp + 100dp + + + + + 4dp + 8dp + 16dp + 32dp + 64dp + + + + @dimen/margin_medium + @dimen/margin_medium + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/values/strings.xml b/app-catalog/samples/wBasis/src/main/res-transition/values/strings.xml new file mode 100644 index 0000000..6c45011 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/values/strings.xml @@ -0,0 +1,40 @@ + + + + BasicTransition + + + + + Scene + 1 + 2 + 3 + 4 + Hello! + This text fades in and out. + + Show Log + Hide Log + From 4ae6604e2a8e4122cd7124f15310a403027937c0 Mon Sep 17 00:00:00 2001 From: wintmain Date: Sun, 28 Sep 2025 00:06:57 +0800 Subject: [PATCH 2/4] [wBasis][refactor]Redefine files' structure --- app-catalog/samples/wBasis/build.gradle | 1 + .../wBasis/src/main/AndroidManifest.xml | 6 ++-- .../gesture/GestureDetectActivity.kt | 2 +- .../gesture/GestureDetectFragment.kt | 2 +- .../{ui/views => }/gesture/GestureListener.kt | 2 +- .../ui/{views => }/layout/ConstraintLayout.kt | 2 +- .../slidingpanelayout/NewsDetailsFragment.kt | 2 +- .../SlidingPaneLayoutMain.kt | 4 +-- .../layout/slidingpanelayout/Sport.kt | 2 +- .../layout/slidingpanelayout/SportsAdapter.kt | 6 ++-- .../layout/slidingpanelayout/SportsData.kt | 2 +- .../slidingpanelayout/SportsListFragment.kt | 4 +-- .../slidingpanelayout/SportsViewModel.kt | 2 +- .../{views => }/recyclerview/CustomAdapter.kt | 4 +-- .../recyclerview/RecyclerViewActivity.kt | 2 +- .../recyclerview/RecyclerViewFragment.kt | 6 ++-- .../res-ext/layout/fragment_sports_list.xml | 4 +-- .../res-ext/layout/fragment_sports_news.xml | 2 +- .../res-ext/layout/sliding_panel_main.xml | 2 +- .../src/main/res-ext/navigation/nav_graph.xml | 4 +-- .../src/main/res-ext/values/strings.xml | 10 ------- .../layout/gesture_detect_main.xml | 4 +-- .../menu/gesture_main.xml | 0 .../src/main/res-gesture/values/strings.xml | 28 +++++++++++++++++++ 24 files changed, 61 insertions(+), 42 deletions(-) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/{ui/views => }/gesture/GestureDetectActivity.kt (98%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/{ui/views => }/gesture/GestureDetectFragment.kt (98%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/{ui/views => }/gesture/GestureListener.kt (99%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/{views => }/layout/ConstraintLayout.kt (99%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/{views => }/layout/slidingpanelayout/NewsDetailsFragment.kt (96%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/{views => }/layout/slidingpanelayout/SlidingPaneLayoutMain.kt (94%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/{views => }/layout/slidingpanelayout/Sport.kt (93%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/{views => }/layout/slidingpanelayout/SportsAdapter.kt (92%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/{views => }/layout/slidingpanelayout/SportsData.kt (98%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/{views => }/layout/slidingpanelayout/SportsListFragment.kt (96%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/{views => }/layout/slidingpanelayout/SportsViewModel.kt (95%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/{views => }/recyclerview/CustomAdapter.kt (93%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/{views => }/recyclerview/RecyclerViewActivity.kt (98%) rename app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/{views => }/recyclerview/RecyclerViewFragment.kt (95%) rename app-catalog/samples/wBasis/src/main/{res-ext => res-gesture}/layout/gesture_detect_main.xml (94%) rename app-catalog/samples/wBasis/src/main/{res-ext => res-gesture}/menu/gesture_main.xml (100%) create mode 100644 app-catalog/samples/wBasis/src/main/res-gesture/values/strings.xml diff --git a/app-catalog/samples/wBasis/build.gradle b/app-catalog/samples/wBasis/build.gradle index 9ea9647..7cef44c 100644 --- a/app-catalog/samples/wBasis/build.gradle +++ b/app-catalog/samples/wBasis/build.gradle @@ -9,6 +9,7 @@ android { res.srcDirs( 'src/main/res', 'src/main/res-ext', + 'src/main/res-gesture', 'src/main/res-transition', ) } diff --git a/app-catalog/samples/wBasis/src/main/AndroidManifest.xml b/app-catalog/samples/wBasis/src/main/AndroidManifest.xml index 3978f68..f2dea46 100644 --- a/app-catalog/samples/wBasis/src/main/AndroidManifest.xml +++ b/app-catalog/samples/wBasis/src/main/AndroidManifest.xml @@ -60,20 +60,20 @@ - diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/gesture/GestureDetectActivity.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/gesture/GestureDetectActivity.kt similarity index 98% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/gesture/GestureDetectActivity.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/gesture/GestureDetectActivity.kt index 3a18a6d..eea3db7 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/gesture/GestureDetectActivity.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/gesture/GestureDetectActivity.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.gesture +package com.wintmain.wBasis.gesture import android.graphics.Color import android.os.Bundle diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/gesture/GestureDetectFragment.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/gesture/GestureDetectFragment.kt similarity index 98% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/gesture/GestureDetectFragment.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/gesture/GestureDetectFragment.kt index 885bf63..a70ab15 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/gesture/GestureDetectFragment.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/gesture/GestureDetectFragment.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.gesture +package com.wintmain.wBasis.gesture import android.annotation.SuppressLint import android.os.Bundle diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/gesture/GestureListener.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/gesture/GestureListener.kt similarity index 99% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/gesture/GestureListener.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/gesture/GestureListener.kt index ee7d023..6174ffa 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/gesture/GestureListener.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/gesture/GestureListener.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.gesture +package com.wintmain.wBasis.gesture import android.os.Build.VERSION import android.view.GestureDetector.SimpleOnGestureListener diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/ConstraintLayout.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/ConstraintLayout.kt similarity index 99% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/ConstraintLayout.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/ConstraintLayout.kt index 5616b91..16d6838 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/ConstraintLayout.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/ConstraintLayout.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.layout +package com.wintmain.wBasis.ui.layout import android.os.Bundle import android.view.View diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/NewsDetailsFragment.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/NewsDetailsFragment.kt similarity index 96% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/NewsDetailsFragment.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/NewsDetailsFragment.kt index 626609e..afa1919 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/NewsDetailsFragment.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/NewsDetailsFragment.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.layout.slidingpanelayout +package com.wintmain.wBasis.ui.layout.slidingpanelayout import android.os.Bundle import android.view.LayoutInflater diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SlidingPaneLayoutMain.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SlidingPaneLayoutMain.kt similarity index 94% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SlidingPaneLayoutMain.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SlidingPaneLayoutMain.kt index 04245b9..408d89f 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SlidingPaneLayoutMain.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SlidingPaneLayoutMain.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.layout.slidingpanelayout +package com.wintmain.wBasis.ui.layout.slidingpanelayout import android.os.Bundle import androidx.appcompat.app.AppCompatActivity @@ -39,7 +39,7 @@ import com.wintmain.wBasis.databinding.SlidingPanelMainBinding documentation = "", tags = ["android-samples", "layout"], ) -class SlidingPaneLayoutMain : AppCompatActivity() { +class SlidingPaneLayoutMain : androidx.appcompat.app.AppCompatActivity() { private lateinit var appBarConfiguration: AppBarConfiguration diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/Sport.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/Sport.kt similarity index 93% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/Sport.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/Sport.kt index 2f0a049..e25c177 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/Sport.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/Sport.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.wintmain.wBasis.ui.views.layout.slidingpanelayout +package com.wintmain.wBasis.ui.layout.slidingpanelayout import com.wintmain.wBasis.R diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsAdapter.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsAdapter.kt similarity index 92% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsAdapter.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsAdapter.kt index 561daa0..f829933 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsAdapter.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsAdapter.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.layout.slidingpanelayout +package com.wintmain.wBasis.ui.layout.slidingpanelayout import android.content.Context import android.view.LayoutInflater @@ -24,10 +24,10 @@ import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import coil.load import com.wintmain.wBasis.databinding.SportsListItemBinding -import com.wintmain.wBasis.ui.views.layout.slidingpanelayout.SportsAdapter.SportsViewHolder +import com.wintmain.wBasis.ui.layout.slidingpanelayout.SportsAdapter.SportsViewHolder class SportsAdapter(private val onItemClicked: (Sport) -> Unit) : - ListAdapter(DiffCallback) { + androidx.recyclerview.widget.ListAdapter(DiffCallback) { private lateinit var context: Context diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsData.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsData.kt similarity index 98% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsData.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsData.kt index e4a7e41..df8126c 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsData.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsData.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.layout.slidingpanelayout +package com.wintmain.wBasis.ui.layout.slidingpanelayout import com.wintmain.wBasis.R diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsListFragment.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsListFragment.kt similarity index 96% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsListFragment.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsListFragment.kt index c1a2460..93cbaaf 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsListFragment.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsListFragment.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.layout.slidingpanelayout +package com.wintmain.wBasis.ui.layout.slidingpanelayout import android.os.Bundle import android.view.LayoutInflater @@ -29,7 +29,7 @@ import com.wintmain.wBasis.databinding.FragmentSportsListBinding /** * A simple [Fragment] subclass as the default destination in the navigation. */ -class SportsListFragment : Fragment() { +class SportsListFragment : androidx.fragment.app.Fragment() { private val sportsViewModel: SportsViewModel by activityViewModels() diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsViewModel.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsViewModel.kt similarity index 95% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsViewModel.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsViewModel.kt index 5aa72dc..5037539 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/layout/slidingpanelayout/SportsViewModel.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/layout/slidingpanelayout/SportsViewModel.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.layout.slidingpanelayout +package com.wintmain.wBasis.ui.layout.slidingpanelayout import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/recyclerview/CustomAdapter.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/recyclerview/CustomAdapter.kt similarity index 93% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/recyclerview/CustomAdapter.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/recyclerview/CustomAdapter.kt index faf128a..faf7458 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/recyclerview/CustomAdapter.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/recyclerview/CustomAdapter.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.recyclerview +package com.wintmain.wBasis.ui.recyclerview import android.view.LayoutInflater import android.view.View @@ -22,7 +22,7 @@ import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.wintmain.wBasis.R -import com.wintmain.wBasis.ui.views.recyclerview.CustomAdapter.ViewHolder +import com.wintmain.wBasis.ui.recyclerview.CustomAdapter.ViewHolder import lib.wintmain.wBasis.logger.Log class CustomAdapter(private val dataSet: Array) : diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/recyclerview/RecyclerViewActivity.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/recyclerview/RecyclerViewActivity.kt similarity index 98% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/recyclerview/RecyclerViewActivity.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/recyclerview/RecyclerViewActivity.kt index 8571f43..13a699f 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/recyclerview/RecyclerViewActivity.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/recyclerview/RecyclerViewActivity.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.wintmain.wBasis.ui.views.recyclerview +package com.wintmain.wBasis.ui.recyclerview import android.os.Bundle import android.view.Menu diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/recyclerview/RecyclerViewFragment.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/recyclerview/RecyclerViewFragment.kt similarity index 95% rename from app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/recyclerview/RecyclerViewFragment.kt rename to app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/recyclerview/RecyclerViewFragment.kt index b90b37a..afdde2b 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/views/recyclerview/RecyclerViewFragment.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/ui/recyclerview/RecyclerViewFragment.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.wintmain.wBasis.ui.views.recyclerview +package com.wintmain.wBasis.ui.recyclerview import android.os.Bundle import android.view.LayoutInflater @@ -26,8 +26,8 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.LayoutManager import com.wintmain.wBasis.R -import com.wintmain.wBasis.ui.views.recyclerview.RecyclerViewFragment.LayoutManagerType.GRID_LAYOUT_MANAGER -import com.wintmain.wBasis.ui.views.recyclerview.RecyclerViewFragment.LayoutManagerType.LINEAR_LAYOUT_MANAGER +import com.wintmain.wBasis.ui.recyclerview.RecyclerViewFragment.LayoutManagerType.GRID_LAYOUT_MANAGER +import com.wintmain.wBasis.ui.recyclerview.RecyclerViewFragment.LayoutManagerType.LINEAR_LAYOUT_MANAGER import java.util.Objects /** diff --git a/app-catalog/samples/wBasis/src/main/res-ext/layout/fragment_sports_list.xml b/app-catalog/samples/wBasis/src/main/res-ext/layout/fragment_sports_list.xml index 98844d0..df0e8ed 100644 --- a/app-catalog/samples/wBasis/src/main/res-ext/layout/fragment_sports_list.xml +++ b/app-catalog/samples/wBasis/src/main/res-ext/layout/fragment_sports_list.xml @@ -22,7 +22,7 @@ android:id="@+id/sliding_pane_layout" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.views.layout.slidingpanelayout.SportsListFragment"> + tools:context=".ui.layout.slidingpanelayout.SportsListFragment"> + android:name="com.wintmain.wBasis.ui.layout.slidingpanelayout.NewsDetailsFragment" /> diff --git a/app-catalog/samples/wBasis/src/main/res-ext/layout/fragment_sports_news.xml b/app-catalog/samples/wBasis/src/main/res-ext/layout/fragment_sports_news.xml index d683520..9121841 100644 --- a/app-catalog/samples/wBasis/src/main/res-ext/layout/fragment_sports_news.xml +++ b/app-catalog/samples/wBasis/src/main/res-ext/layout/fragment_sports_news.xml @@ -18,7 +18,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - tools:context="com.wintmain.wBasis.ui.views.layout.slidingpanelayout.SlidingPaneLayoutMain" + tools:context="com.wintmain.wBasis.ui.layout.slidingpanelayout.SlidingPaneLayoutMain" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="16dp" diff --git a/app-catalog/samples/wBasis/src/main/res-ext/layout/sliding_panel_main.xml b/app-catalog/samples/wBasis/src/main/res-ext/layout/sliding_panel_main.xml index f9e6236..8dcc7ac 100644 --- a/app-catalog/samples/wBasis/src/main/res-ext/layout/sliding_panel_main.xml +++ b/app-catalog/samples/wBasis/src/main/res-ext/layout/sliding_panel_main.xml @@ -21,7 +21,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.views.layout.slidingpanelayout.SlidingPaneLayoutMain"> + tools:context=".ui.layout.slidingpanelayout.SlidingPaneLayoutMain"> @@ -33,7 +33,7 @@ diff --git a/app-catalog/samples/wBasis/src/main/res-ext/values/strings.xml b/app-catalog/samples/wBasis/src/main/res-ext/values/strings.xml index a80a823..19010cb 100644 --- a/app-catalog/samples/wBasis/src/main/res-ext/values/strings.xml +++ b/app-catalog/samples/wBasis/src/main/res-ext/values/strings.xml @@ -24,16 +24,6 @@ HttpsURLConnection. AsyncTask is used to perform the fetch on a background thread. - ]]> - - - diff --git a/app-catalog/samples/wBasis/src/main/res-ext/layout/gesture_detect_main.xml b/app-catalog/samples/wBasis/src/main/res-gesture/layout/gesture_detect_main.xml similarity index 94% rename from app-catalog/samples/wBasis/src/main/res-ext/layout/gesture_detect_main.xml rename to app-catalog/samples/wBasis/src/main/res-gesture/layout/gesture_detect_main.xml index 77975ec..cf533ab 100644 --- a/app-catalog/samples/wBasis/src/main/res-ext/layout/gesture_detect_main.xml +++ b/app-catalog/samples/wBasis/src/main/res-gesture/layout/gesture_detect_main.xml @@ -1,6 +1,6 @@ + + + + + + \ No newline at end of file From 87dbf6ff4b805d189fd258cbf19b301d29b5848a Mon Sep 17 00:00:00 2001 From: wintmain Date: Wed, 1 Oct 2025 00:36:37 +0800 Subject: [PATCH 3/4] [wBasis][feat]Add custom transition sample --- .../wBasis/src/main/AndroidManifest.xml | 5 + .../transition/CustomTransitionActivity.java | 116 ++++++++++++++++++ .../transition/CustomTransitionFragment.java | 87 +++++++++++++ .../wBasis/transition/util/ChangeColor.java | 111 +++++++++++++++++ .../activity_custom_transition.xml | 72 +++++++++++ .../layout/activity_custom_transition.xml | 66 ++++++++++ .../res-transition/layout/custom_scene1.xml | 47 +++++++ .../res-transition/layout/custom_scene2.xml | 47 +++++++ .../res-transition/layout/custom_scene3.xml | 47 +++++++ .../layout/fragment_custom_transition.xml | 36 ++++++ .../main/res-transition/values/strings.xml | 10 ++ 11 files changed, 644 insertions(+) create mode 100644 app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/CustomTransitionActivity.java create mode 100644 app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/CustomTransitionFragment.java create mode 100644 app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/util/ChangeColor.java create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/layout-w720dp/activity_custom_transition.xml create mode 100755 app-catalog/samples/wBasis/src/main/res-transition/layout/activity_custom_transition.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene1.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene2.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene3.xml create mode 100644 app-catalog/samples/wBasis/src/main/res-transition/layout/fragment_custom_transition.xml diff --git a/app-catalog/samples/wBasis/src/main/AndroidManifest.xml b/app-catalog/samples/wBasis/src/main/AndroidManifest.xml index f2dea46..95af7a2 100644 --- a/app-catalog/samples/wBasis/src/main/AndroidManifest.xml +++ b/app-catalog/samples/wBasis/src/main/AndroidManifest.xml @@ -373,6 +373,11 @@ android:name=".transition.BasicTransitionActivity" android:exported="true" android:theme="@style/Theme.AppCompat.DayNight" /> + + \ No newline at end of file diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/CustomTransitionActivity.java b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/CustomTransitionActivity.java new file mode 100644 index 0000000..b90db19 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/CustomTransitionActivity.java @@ -0,0 +1,116 @@ +/* + * Copyright 2023-2025 wintmain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.wintmain.wBasis.transition; + +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.TextView; +import android.widget.ViewAnimator; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.FragmentTransaction; +import com.google.android.catalog.framework.annotations.Sample; +import com.wintmain.wBasis.R; +import lib.wintmain.wBasis.logger.Log; +import lib.wintmain.wBasis.logger.LogFragment; +import lib.wintmain.wBasis.logger.LogWrapper; +import lib.wintmain.wBasis.logger.MessageOnlyLogFilter; + +@Sample(name = "CustomTransition", + description = "自定义的变化", + tags = {"android-samples", "animation-samples"} +) +public class CustomTransitionActivity extends AppCompatActivity { + public static final String TAG = "MainActivity"; + + // Whether the Log Fragment is currently shown + private boolean mLogShown; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_custom_transition); + + if (savedInstanceState == null) { + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + CustomTransitionFragment fragment = new CustomTransitionFragment(); + transaction.replace(R.id.sample_content_fragment, fragment); + transaction.commit(); + } + } + + @Override + protected void onStart() { + super.onStart(); + initializeLogging(); + } + + // Set up targets to receive log data + /** Create a chain of targets that will receive log data */ + public void initializeLogging() { + // Wraps Android's native log framework. + LogWrapper logWrapper = new LogWrapper(); + // Using Log, front-end to the logging chain, emulates android.util.log method signatures. + Log.setLogNode(logWrapper); + + // Filter strips out everything except the message text. + MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter(); + logWrapper.setNext(msgFilter); + + // On screen logging via a fragment with a TextView. + LogFragment logFragment = (LogFragment) getSupportFragmentManager() + .findFragmentById(R.id.log_fragment); + msgFilter.setNext(logFragment.getLogView()); + + Log.i(TAG, "Ready"); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.main, menu); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + MenuItem logToggle = menu.findItem(R.id.menu_toggle_log); + logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator); + logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log); + + return super.onPrepareOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.menu_toggle_log) { + mLogShown = !mLogShown; + ViewAnimator output = (ViewAnimator) findViewById(R.id.sample_output); + if (mLogShown) { + output.setDisplayedChild(1); + } else { + output.setDisplayedChild(0); + } + supportInvalidateOptionsMenu(); + return true; + } else if (item.getItemId() == R.id.clear_action) { + TextView tv = (TextView)findViewById(R.id.custom_clear_tv); + tv.setText(""); + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/CustomTransitionFragment.java b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/CustomTransitionFragment.java new file mode 100644 index 0000000..e6520ba --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/CustomTransitionFragment.java @@ -0,0 +1,87 @@ +/* + * Copyright 2023-2025 wintmain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.wintmain.wBasis.transition; + +import android.content.Context; +import android.os.Bundle; +import android.transition.Scene; +import android.transition.Transition; +import android.transition.TransitionManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import com.wintmain.wBasis.R; +import com.wintmain.wBasis.transition.util.ChangeColor; +import lib.wintmain.wBasis.logger.Log; + +public class CustomTransitionFragment extends Fragment implements View.OnClickListener { + private static final String TAG = CustomTransitionFragment.class.getSimpleName(); + + private static final String STATE_CURRENT_SCENE = "current_scene"; + + /** These are the Scenes we use. */ + private Scene[] mScenes; + + /** The current index for mScenes. */ + private int mCurrentScene; + /** This is the custom Transition we use in this sample. */ + private Transition mTransition; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_custom_transition, container, false); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + Context context = getActivity(); + FrameLayout container = (FrameLayout) view.findViewById(R.id.container); + view.findViewById(R.id.show_next_scene).setOnClickListener(this); + if (null != savedInstanceState) { + mCurrentScene = savedInstanceState.getInt(STATE_CURRENT_SCENE); + } + // We set up the Scenes here. + mScenes = new Scene[] { + Scene.getSceneForLayout(container, R.layout.custom_scene1, context), + Scene.getSceneForLayout(container, R.layout.custom_scene2, context), + Scene.getSceneForLayout(container, R.layout.custom_scene3, context), + }; + // This is the custom Transition. + mTransition = new ChangeColor(); + // Show the initial Scene. + TransitionManager.go(mScenes[mCurrentScene % mScenes.length]); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(STATE_CURRENT_SCENE, mCurrentScene); + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.show_next_scene) { + mCurrentScene = (mCurrentScene + 1) % mScenes.length; + Log.i(TAG, "Transitioning to scene #" + mCurrentScene); + // Pass the custom Transition as second argument for TransitionManager.go + TransitionManager.go(mScenes[mCurrentScene], mTransition); + } + } +} diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/util/ChangeColor.java b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/util/ChangeColor.java new file mode 100644 index 0000000..0e559d3 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/util/ChangeColor.java @@ -0,0 +1,111 @@ +/* + * Copyright 2023-2025 wintmain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.wintmain.wBasis.transition.util; + +import android.animation.Animator; +import android.animation.ArgbEvaluator; +import android.animation.ValueAnimator; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.transition.Transition; +import android.transition.TransitionValues; +import android.view.View; +import android.view.ViewGroup; +import androidx.annotation.NonNull; + +public class ChangeColor extends Transition { + /** Key to store a color value in TransitionValues object */ + private static final String PROPNAME_BACKGROUND = "customtransition:change_color:background"; + + @Override + public void captureStartValues(TransitionValues transitionValues) { + captureValues(transitionValues); + } + + // Capture the value of the background drawable property for a target in the ending Scene. + @Override + public void captureEndValues(TransitionValues transitionValues) { + captureValues(transitionValues); + } + + // BEGIN_INCLUDE (capture_values) + /** + * Convenience method: Add the background Drawable property value + * to the TransitionsValues.value Map for a target. + */ + private void captureValues(TransitionValues values) { + // Capture the property values of views for later use + values.values.put(PROPNAME_BACKGROUND, values.view.getBackground()); + } + // END_INCLUDE (capture_values) + + // BEGIN_INCLUDE (create_animator) + // Create an animation for each target that is in both the starting and ending Scene. For each + // pair of targets, if their background property value is a color (rather than a graphic), + // create a ValueAnimator based on an ArgbEvaluator that interpolates between the starting and + // ending color. Also create an update listener that sets the View background color for each + // animation frame + @Override + public Animator createAnimator(@NonNull ViewGroup sceneRoot, + TransitionValues startValues, TransitionValues endValues) { + // This transition can only be applied to views that are on both starting and ending scenes. + if (null == startValues || null == endValues) { + return null; + } + // Store a convenient reference to the target. Both the starting and ending layout have the + // same target. + final View view = endValues.view; + // Store the object containing the background property for both the starting and ending + // layouts. + Drawable startBackground = (Drawable) startValues.values.get(PROPNAME_BACKGROUND); + Drawable endBackground = (Drawable) endValues.values.get(PROPNAME_BACKGROUND); + // This transition changes background colors for a target. It doesn't animate any other + // background changes. If the property isn't a ColorDrawable, ignore the target. + if (startBackground instanceof ColorDrawable startColor && endBackground instanceof ColorDrawable endColor) { + // If the background color for the target in the starting and ending layouts is + // different, create an animation. + if (startColor.getColor() != endColor.getColor()) { + // Create a new Animator object to apply to the targets as the transitions framework + // changes from the starting to the ending layout. Use the class ValueAnimator, + // which provides a timing pulse to change property values provided to it. The + // animation runs on the UI thread. The Evaluator controls what type of + // interpolation is done. In this case, an ArgbEvaluator interpolates between two + // #argb values, which are specified as the 2nd and 3rd input arguments. + ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(), + startColor.getColor(), endColor.getColor()); + // Add an update listener to the Animator object. + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + Object value = animation.getAnimatedValue(); + // Each time the ValueAnimator produces a new frame in the animation, change + // the background color of the target. Ensure that the value isn't null. + if (null != value) { + view.setBackgroundColor((Integer) value); + } + } + }); + // Return the Animator object to the transitions framework. As the framework changes + // between the starting and ending layouts, it applies the animation you've created. + return animator; + } + } + // For non-ColorDrawable backgrounds, we just return null, and no animation will take place. + return null; + } + // END_INCLUDE (create_animator) +} diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout-w720dp/activity_custom_transition.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout-w720dp/activity_custom_transition.xml new file mode 100644 index 0000000..f686267 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout-w720dp/activity_custom_transition.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout/activity_custom_transition.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout/activity_custom_transition.xml new file mode 100755 index 0000000..050c3ef --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/activity_custom_transition.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene1.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene1.xml new file mode 100644 index 0000000..231a50e --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene1.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene2.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene2.xml new file mode 100644 index 0000000..e471bcf --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene2.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene3.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene3.xml new file mode 100644 index 0000000..6e68754 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene3.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout/fragment_custom_transition.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout/fragment_custom_transition.xml new file mode 100644 index 0000000..776cf96 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/fragment_custom_transition.xml @@ -0,0 +1,36 @@ + + + + +