diff --git a/app-catalog/samples/wBasis/build.gradle b/app-catalog/samples/wBasis/build.gradle index 3860e29..2a1e011 100644 --- a/app-catalog/samples/wBasis/build.gradle +++ b/app-catalog/samples/wBasis/build.gradle @@ -1,3 +1,19 @@ +/* + * 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. + */ + apply from: "$rootDir/gradle/sample-build.gradle" apply plugin: 'kotlin-parcelize' @@ -9,6 +25,8 @@ 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/libwBasis/build.gradle b/app-catalog/samples/wBasis/libwBasis/build.gradle index 67af3e9..251c0ab 100644 --- a/app-catalog/samples/wBasis/libwBasis/build.gradle +++ b/app-catalog/samples/wBasis/libwBasis/build.gradle @@ -1,3 +1,19 @@ +/* + * 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. + */ + apply from: "$rootDir/gradle/sample-build.gradle" android { 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..f8117c0 --- /dev/null +++ b/app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/view/SlidingTabLayout.java @@ -0,0 +1,307 @@ +/* + * 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 { + 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); + } + } + + /** + * 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 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..6defc82 --- /dev/null +++ b/app-catalog/samples/wBasis/libwBasis/src/main/java/lib/wintmain/wBasis/view/SlidingTabStrip.java @@ -0,0 +1,200 @@ +/* + * 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 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 SlidingTabLayout.TabColorizer mCustomTabColorizer; + 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)); + } + + /** + * 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); + } + + 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); + } + } + + 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..883c0c2 100644 --- a/app-catalog/samples/wBasis/src/main/AndroidManifest.xml +++ b/app-catalog/samples/wBasis/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - - - - + + android:exported="true" + android:process=":remote" /> + + + + \ No newline at end of file diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/PlaceHolderActivity.java b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/PlaceHolderActivity.java index 04fa3f9..3dac871 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/PlaceHolderActivity.java +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/PlaceHolderActivity.java @@ -40,7 +40,7 @@ public class PlaceHolderActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.pft_activity_main); + setContentView(R.layout.activity_pft_main); // 初始化一些三方库 initLibs(getApplication()); @@ -61,7 +61,8 @@ public void onTitleClick(TitleBarExt titleBar) { newIntent.putExtra(AlarmClock.EXTRA_MINUTES, 30); newIntent.setAction(AlarmClock.ACTION_SET_ALARM); newIntent.putExtra(AlarmClock.EXTRA_SKIP_UI, true); - newIntent.setComponent(new ComponentName("com.android.deskclock", "com.android.deskclock.HandleApiCalls")); + newIntent.setComponent(new ComponentName("com.android.deskclock", + "com.android.deskclock.HandleApiCalls")); try { startActivity(newIntent); ToastUtils.show("你点击了中间,并且新建了一个9:30的闹钟"); diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/AidlSampleActivity.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/AidlSampleActivity.kt index c472e89..6bb9b75 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/AidlSampleActivity.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/AidlSampleActivity.kt @@ -27,11 +27,12 @@ import androidx.appcompat.app.AppCompatActivity import com.google.android.catalog.framework.annotations.Sample import lib.wintmain.wToaster.toast.ToastUtils -@Sample(name = "AIDL-SampleActivity", description = "AIDL简单示例", tags =["A-Self_demos"]) -class AidlSampleActivity: AppCompatActivity() { +@Sample(name = "AIDL-SampleActivity", description = "AIDL简单示例", tags = ["A-Self_demos"]) +class AidlSampleActivity : AppCompatActivity() { companion object { private const val TAG = "AidlSampleActivity" } + var peopleManager: IPeopleManager? = null override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/People.java b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/People.java index d02a994..0be6cce 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/People.java +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/People.java @@ -22,6 +22,17 @@ public class People implements Parcelable { + // 反序列化功能由CREATOR来完成,其内部标明了如何创建序列化对象和数组, + // 并通过Parcel的一系列read方法来完成反序列化过程。 + public static final Parcelable.Creator CREATOR = new Parcelable.Creator<>() { + public People createFromParcel(Parcel in) { + return new People(in); + } + + public People[] newArray(int size) { + return new People[size]; + } + }; public int pId; public String pName; @@ -65,19 +76,6 @@ public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(pName); } - // 反序列化功能由CREATOR来完成,其内部标明了如何创建序列化对象和数组, - // 并通过Parcel的一系列read方法来完成反序列化过程。 - public static final Parcelable.Creator CREATOR = new Parcelable.Creator<>() { - public People createFromParcel(Parcel in) { - return new People(in); - } - - public People[] newArray(int size) { - return new People[size]; - } - }; - - @NonNull @Override public String toString() { diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/PeopleRemoteService.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/PeopleRemoteService.kt index 4e61167..29775ff 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/PeopleRemoteService.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/aidl/PeopleRemoteService.kt @@ -27,6 +27,7 @@ import java.util.concurrent.CopyOnWriteArrayList // 服务端代码,客户端见[AidlSampleActivity.java] class PeopleRemoteService : Service() { val mPeopleList = CopyOnWriteArrayList() + // 客户端注册和移除注册过程中使用的虽是同一个客户端对象, // 但通过Binder传递到服务端后,产生了两个不同的对象。 // 因为对象是不能跨进程直接传输的,对象的跨进程传输本质上都是反序列化的过程 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 96% 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..f9a4349 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 @@ -40,7 +40,7 @@ class GestureDetectActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.gesture_detect_main) + setContentView(R.layout.activity_gesture_detect_main) val transaction = supportFragmentManager.beginTransaction() transaction.add(GestureDetectFragment(), FRAG).commit() 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/overview/DbHelper.java b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/DbHelper.java index 6ea0983..72bf94e 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/DbHelper.java +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/DbHelper.java @@ -30,33 +30,16 @@ public class DbHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "demo_whitelist.db"; private static final int DATABASE_VERSION = 1; - - public static class WhitelistEntry implements BaseColumns { - public static final String TABLE_NAME = "whitelist"; - public static final String COLUMN_PACKAGE_NAME = "package_name"; - } - private static final String SQL_CREATE_ENTRIES = "CREATE TABLE " + WhitelistEntry.TABLE_NAME - + " (" + WhitelistEntry._ID + " INTEGER PRIMARY KEY," + WhitelistEntry.COLUMN_PACKAGE_NAME + + " (" + WhitelistEntry._ID + " INTEGER PRIMARY KEY," + + WhitelistEntry.COLUMN_PACKAGE_NAME + " TEXT)"; - private static final String SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS " + WhitelistEntry.TABLE_NAME; - + private static final String SQL_DELETE_ENTRIES = + "DROP TABLE IF EXISTS " + WhitelistEntry.TABLE_NAME; public DbHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL(SQL_CREATE_ENTRIES); - Log.d("DbHelper", "Database created"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int i, int i1) { - db.execSQL(SQL_DELETE_ENTRIES); - onCreate(db); - } - public static void addToWhitelist(Context context, String packageName) { DbHelper dbHelper = new DbHelper(context); SQLiteDatabase db = null; @@ -80,7 +63,7 @@ public static void removeFromWhitelist(Context context, String packageName) { SQLiteDatabase db = dbHelper.getWritableDatabase(); String selection = WhitelistEntry.COLUMN_PACKAGE_NAME + " = ?"; - String[] selectionArgs = { packageName }; + String[] selectionArgs = {packageName}; db.delete(WhitelistEntry.TABLE_NAME, selection, selectionArgs); db.close(); @@ -91,7 +74,7 @@ public static List getWhitelist(Context context) { DbHelper dbHelper = new DbHelper(context); SQLiteDatabase db = dbHelper.getReadableDatabase(); - String[] projection = { WhitelistEntry.COLUMN_PACKAGE_NAME }; + String[] projection = {WhitelistEntry.COLUMN_PACKAGE_NAME}; Cursor cursor = db.query( WhitelistEntry.TABLE_NAME, @@ -115,4 +98,21 @@ public static List getWhitelist(Context context) { return whitelist; } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(SQL_CREATE_ENTRIES); + Log.d("DbHelper", "Database created"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int i, int i1) { + db.execSQL(SQL_DELETE_ENTRIES); + onCreate(db); + } + + public static class WhitelistEntry implements BaseColumns { + public static final String TABLE_NAME = "whitelist"; + public static final String COLUMN_PACKAGE_NAME = "package_name"; + } } diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep1_UI.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep1_UI.kt index 9b802bd..d060157 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep1_UI.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep1_UI.kt @@ -117,43 +117,43 @@ class CodeToLayout : Fragment() { * Java public class EpOne_1 extends AppCompatActivity { - public TextView text2; +public TextView text2; - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - // 1. xml方式 +@Override +protected void onCreate(@Nullable Bundle savedInstanceState) { +super.onCreate(savedInstanceState); +// 1. xml方式 // setContentView(R.layout.ep1_1); - // 2. code方式 - // 创建帧布局管理器 - FrameLayout frameLayout = new FrameLayout(this); - // 设置背景 - frameLayout.setBackground( - ResourcesCompat.getDrawable(this.getResources(), R.drawable.ic_launcher_foreground, - null)); - // 设置在Activity中显示frameLayout - setContentView(frameLayout); - // 创建一个TextView组件text1,设置其文字大小和颜色,并将其添加到布局管理器中 - TextView text1 = new TextView(this); - text1.setText("在代码中控制UI界面"); // 设置显示的文字 - text1.setTextSize(TypedValue.COMPLEX_UNIT_PX, 24); // 设置文字大小,单位为像素 - text1.setTextColor(Color.rgb(1, 1, 1)); // 设置文字的颜色 - frameLayout.addView(text1); // 将 text1添加到布局管理器中 - - // 实例化text2组件,设置其显示文字、文字大小、颜色和布局 - text2 = new TextView(this); - text2.setText("单击进入Android…"); // 设置显示文字 - text2.setTextSize(TypedValue.COMPLEX_UNIT_PX, 24); // 设置文字大小,单位为像素 - text2.setTextColor(Color.rgb(1, 1, 1)); // 设置文字的颜色 - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); // 创建保存布局参数的对象 - params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL; // 设置居中显示 - text2.setLayoutParams(params); // 设置布局参数 - } +// 2. code方式 +// 创建帧布局管理器 +FrameLayout frameLayout = new FrameLayout(this); +// 设置背景 +frameLayout.setBackground( +ResourcesCompat.getDrawable(this.getResources(), R.drawable.ic_launcher_foreground, +null)); +// 设置在Activity中显示frameLayout +setContentView(frameLayout); +// 创建一个TextView组件text1,设置其文字大小和颜色,并将其添加到布局管理器中 +TextView text1 = new TextView(this); +text1.setText("在代码中控制UI界面"); // 设置显示的文字 +text1.setTextSize(TypedValue.COMPLEX_UNIT_PX, 24); // 设置文字大小,单位为像素 +text1.setTextColor(Color.rgb(1, 1, 1)); // 设置文字的颜色 +frameLayout.addView(text1); // 将 text1添加到布局管理器中 + +// 实例化text2组件,设置其显示文字、文字大小、颜色和布局 +text2 = new TextView(this); +text2.setText("单击进入Android…"); // 设置显示文字 +text2.setTextSize(TypedValue.COMPLEX_UNIT_PX, 24); // 设置文字大小,单位为像素 +text2.setTextColor(Color.rgb(1, 1, 1)); // 设置文字的颜色 +FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( +ViewGroup.LayoutParams.WRAP_CONTENT, +ViewGroup.LayoutParams.WRAP_CONTENT); // 创建保存布局参数的对象 +params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL; // 设置居中显示 +text2.setLayoutParams(params); // 设置布局参数 } -*/ +} + */ @Sample( name = "03. Rabbit Listener", @@ -174,15 +174,15 @@ class RabbitLayout : AppCompatActivity() { val frameLayout: FrameLayout = findViewById(R.id.mylayout) // Attention here. val rabbit = RabbitView(this@RabbitLayout) -/* rabbit.setOnTouchListener { _, event -> - rabbit.bitmapX = event.x - rabbit.bitmapY = event.y - rabbit.invalidate() - Toast.makeText(baseContext, "You touch this rabbit.", LENGTH_SHORT).show() - true - }*/ - - rabbit.setOnLongClickListener{ + /* rabbit.setOnTouchListener { _, event -> + rabbit.bitmapX = event.x + rabbit.bitmapY = event.y + rabbit.invalidate() + Toast.makeText(baseContext, "You touch this rabbit.", LENGTH_SHORT).show() + true + }*/ + + rabbit.setOnLongClickListener { Toast.makeText(baseContext, "Long click.", LENGTH_SHORT).show() true } @@ -213,55 +213,55 @@ class RabbitView(context: Context) : View(context) { } /** -* Java + * Java public class EpOne_4 extends Activity { - // AppCompatActivity -> 会有title bar,还有其他的一些 - - @SuppressLint("ClickableViewAccessibility") - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.ep1_4); - - FrameLayout frameLayout = findViewById(R.id.mylayout); // 获取帧布局管理器 - final RabbitView rabbit = new RabbitView(EpOne_4.this); // 创建并实例化RabbitView类 - // 为小兔子添加触摸事件监听器 - rabbit.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - rabbit.bitmapX = event.getX(); // 设置小兔子显示位置的X坐标 - rabbit.bitmapY = event.getY(); // 设置小兔子显示位置的Y坐标 - rabbit.invalidate(); // 重绘rabbit组件 - Toast.makeText(getBaseContext(), "You touch this rabbit.", LENGTH_SHORT).show(); - return true; - } - }); - frameLayout.addView(rabbit); // 将rabbit添加到布局管理器中 - } +// AppCompatActivity -> 会有title bar,还有其他的一些 + +@SuppressLint("ClickableViewAccessibility") +@Override +protected void onCreate(Bundle savedInstanceState) { +super.onCreate(savedInstanceState); +setContentView(R.layout.ep1_4); + +FrameLayout frameLayout = findViewById(R.id.mylayout); // 获取帧布局管理器 +final RabbitView rabbit = new RabbitView(EpOne_4.this); // 创建并实例化RabbitView类 +// 为小兔子添加触摸事件监听器 +rabbit.setOnTouchListener(new View.OnTouchListener() { +@Override +public boolean onTouch(View v, MotionEvent event) { +rabbit.bitmapX = event.getX(); // 设置小兔子显示位置的X坐标 +rabbit.bitmapY = event.getY(); // 设置小兔子显示位置的Y坐标 +rabbit.invalidate(); // 重绘rabbit组件 +Toast.makeText(getBaseContext(), "You touch this rabbit.", LENGTH_SHORT).show(); +return true; +} +}); +frameLayout.addView(rabbit); // 将rabbit添加到布局管理器中 +} } class RabbitView extends View { - public float bitmapX; // 小兔子显示位置的X坐标 - public float bitmapY; // 小兔子显示位置的Y坐标 +public float bitmapX; // 小兔子显示位置的X坐标 +public float bitmapY; // 小兔子显示位置的Y坐标 - public RabbitView(Context context) { // 重写构造方法 - super(context); - bitmapX = 0; - bitmapY = 0; - } +public RabbitView(Context context) { // 重写构造方法 +super(context); +bitmapX = 0; +bitmapY = 0; +} - @Override - protected void onDraw(@NonNull Canvas canvas) { - super.onDraw(canvas); - Paint paint = new Paint(); // 创建并实例化Paint的对象 - Bitmap bitmap = decodeResource(this.getResources(), R.drawable.img06); // 根据图片生成位图对象 - canvas.drawBitmap(bitmap, bitmapX, bitmapY, paint); // 绘制小兔子 - if (bitmap.isRecycled()) { // 判断图片是否回收 - bitmap.recycle(); // 强制回收图片 - } - } +@Override +protected void onDraw(@NonNull Canvas canvas) { +super.onDraw(canvas); +Paint paint = new Paint(); // 创建并实例化Paint的对象 +Bitmap bitmap = decodeResource(this.getResources(), R.drawable.img06); // 根据图片生成位图对象 +canvas.drawBitmap(bitmap, bitmapX, bitmapY, paint); // 绘制小兔子 +if (bitmap.isRecycled()) { // 判断图片是否回收 +bitmap.recycle(); // 强制回收图片 } -*/ +} +} + */ @Sample( name = "04. Register Member", @@ -421,8 +421,10 @@ class RadioGroupDemo : AppCompatActivity() { for (i in 0 until sex2.childCount) { val r = sex2.getChildAt(i) as RadioButton // 根据索引值获取单选按钮的值 if (r.isChecked) { // 判断是否选中 - Toast.makeText(this@RadioGroupDemo, "你选择的是:" + r.getText(), - LENGTH_SHORT).show() + Toast.makeText( + this@RadioGroupDemo, "你选择的是:" + r.getText(), + LENGTH_SHORT + ).show() break // 跳出循环,单选 } } diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep2_UIWidget.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep2_UIWidget.kt index f913453..e95fc26 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep2_UIWidget.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep2_UIWidget.kt @@ -167,7 +167,7 @@ class ep2_2 : AppCompatActivity() { } } -@Sample(name = "SeekBar", description = "拖动条展示", tags = ["A-Self_demos"],) +@Sample(name = "SeekBar", description = "拖动条展示", tags = ["A-Self_demos"]) class ep2_3 : AppCompatActivity() { private var seekbar: SeekBar? = null // 拖动条 diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep5_Menu.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep5_Menu.kt index 2821a93..88b8323 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep5_Menu.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/overview/Ep5_Menu.kt @@ -233,15 +233,19 @@ class ep5_6 : AppCompatActivity() { R.id.color1 -> { textView!!.setTextColor(Color.rgb(255, 0, 0)) } + R.id.color2 -> { textView!!.setTextColor(Color.rgb(0, 255, 0)) } + R.id.color3 -> { textView!!.setTextColor(Color.rgb(0, 0, 255)) } + R.id.color4 -> { textView!!.setTextColor(Color.rgb(255, 180, 0)) } + else -> { textView!!.setTextColor(Color.rgb(255, 255, 255)) } diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/telephony/networkconnectivity/NetworkConnActivity.java b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/telephony/networkconnectivity/NetworkConnActivity.java index 42b2128..f9852d3 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/telephony/networkconnectivity/NetworkConnActivity.java +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/telephony/networkconnectivity/NetworkConnActivity.java @@ -57,7 +57,7 @@ public class NetworkConnActivity extends AppCompatActivity implements DownloadCa @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.conn_main); + setContentView(R.layout.activity_connectivity_main); mDataText = findViewById(R.id.data_text); // 这里的网站换成国内的,便于访问 mNetworkFragment = 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..83c075b --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/BasicTransitionActivity.java @@ -0,0 +1,121 @@ +/* + * 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.activity_basic_transition); + + 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..b965d06 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/BasicTransitionFragment.java @@ -0,0 +1,118 @@ +/* + * 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 BasicTransitionFragment() { + } + + public static BasicTransitionFragment newInstance() { + return new 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/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..80f9e86 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/CustomTransitionActivity.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.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..404716b --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/CustomTransitionFragment.java @@ -0,0 +1,88 @@ +/* + * 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..b09f29a --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/transition/util/ChangeColor.java @@ -0,0 +1,113 @@ +/* + * 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/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 92% 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..c1646bc 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,10 +14,9 @@ * 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 import androidx.navigation.findNavController import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.AppBarConfiguration @@ -39,7 +38,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 @@ -61,5 +60,4 @@ class SlidingPaneLayoutMain : AppCompatActivity() { return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() } - } \ No newline at end of file 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 89% 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..e20c5f0 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,27 +14,26 @@ * 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 import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil -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 class SportsViewHolder(private var binding: SportsListItemBinding) : RecyclerView.ViewHolder(binding.root) { - fun bind(sport: Sport, context:Context) { + fun bind(sport: Sport, context: Context) { binding.title.text = context.getString(sport.titleResourceId) binding.subTitle.text = context.getString(sport.subTitleResourceId) // Load the images into the ImageView using the Coil library. 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 97% 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..cfbfb3b 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,14 +14,14 @@ * limitations under the License. */ -package com.wintmain.wBasis.ui.views.layout.slidingpanelayout +package com.wintmain.wBasis.ui.layout.slidingpanelayout import com.wintmain.wBasis.R /** * Sports data */ -object SportsData{ +object SportsData { fun getSportsData(): ArrayList { return arrayListOf( Sport( 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 97% 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..eaa146a 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 @@ -45,7 +45,7 @@ class RecyclerViewActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.recyclerview_activity_main) + setContentView(R.layout.activity_recyclerview_main) if (savedInstanceState == null) { val transaction = supportFragmentManager.beginTransaction() 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 93% 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..37a8f38 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 /** @@ -66,7 +66,7 @@ class RecyclerViewFragment : Fragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - val rootView = inflater.inflate(R.layout.recycler_view_frag, container, false) + val rootView = inflater.inflate(R.layout.fragment_recyclerview, container, false) rootView.tag = TAG mRecyclerView = rootView.findViewById(R.id.recyclerView) diff --git a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/webview/CustomActionWebViewActivity.kt b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/webview/CustomActionWebViewActivity.kt index 749ce46..0f65ce1 100644 --- a/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/webview/CustomActionWebViewActivity.kt +++ b/app-catalog/samples/wBasis/src/main/java/com/wintmain/wBasis/webview/CustomActionWebViewActivity.kt @@ -30,7 +30,7 @@ class CustomActionWebViewActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.custom_action_webview_activity) + setContentView(R.layout.activity_custom_action_webview) mWebView = findViewById(R.id.webview) val list: MutableList = ArrayList() diff --git a/app-catalog/samples/wBasis/src/main/res-ext/layout/conn_main.xml b/app-catalog/samples/wBasis/src/main/res-ext/layout/activity_connectivity_main.xml similarity index 100% rename from app-catalog/samples/wBasis/src/main/res-ext/layout/conn_main.xml rename to app-catalog/samples/wBasis/src/main/res-ext/layout/activity_connectivity_main.xml diff --git a/app-catalog/samples/wBasis/src/main/res-ext/layout/pft_activity_main.xml b/app-catalog/samples/wBasis/src/main/res-ext/layout/activity_pft_main.xml similarity index 100% rename from app-catalog/samples/wBasis/src/main/res-ext/layout/pft_activity_main.xml rename to app-catalog/samples/wBasis/src/main/res-ext/layout/activity_pft_main.xml diff --git a/app-catalog/samples/wBasis/src/main/res-ext/layout/recyclerview_activity_main.xml b/app-catalog/samples/wBasis/src/main/res-ext/layout/activity_recyclerview_main.xml similarity index 100% rename from app-catalog/samples/wBasis/src/main/res-ext/layout/recyclerview_activity_main.xml rename to app-catalog/samples/wBasis/src/main/res-ext/layout/activity_recyclerview_main.xml diff --git a/app-catalog/samples/wBasis/src/main/res-ext/layout/content_main.xml b/app-catalog/samples/wBasis/src/main/res-ext/layout/content_main.xml index a7164a5..718d3a1 100644 --- a/app-catalog/samples/wBasis/src/main/res-ext/layout/content_main.xml +++ b/app-catalog/samples/wBasis/src/main/res-ext/layout/content_main.xml @@ -1,5 +1,4 @@ - - - diff --git a/app-catalog/samples/wBasis/src/main/res-ext/layout/recycler_view_frag.xml b/app-catalog/samples/wBasis/src/main/res-ext/layout/fragment_recyclerview.xml similarity index 100% rename from app-catalog/samples/wBasis/src/main/res-ext/layout/recycler_view_frag.xml rename to app-catalog/samples/wBasis/src/main/res-ext/layout/fragment_recyclerview.xml 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..15e0689 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 @@ -1,5 +1,4 @@ - - - + tools:context=".ui.layout.slidingpanelayout.SportsListFragment"> + android:padding="8dp" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" /> + android:layout_weight="1" /> 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..0ffc752 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 @@ -14,64 +14,63 @@ ~ limitations under the License. --> - + app:cardCornerRadius="8dp" + tools:context="com.wintmain.wBasis.ui.layout.slidingpanelayout.SlidingPaneLayoutMain"> - + - + - + - + - + - + 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..047e083 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 @@ -1,5 +1,4 @@ - - - + tools:context=".ui.layout.slidingpanelayout.SlidingPaneLayoutMain"> - - + app:cardElevation="4dp" + app:strokeColor="@android:color/background_light" + app:strokeWidth="1dp"> + android:layout_width="match_parent" + android:layout_height="wrap_content"> - + diff --git a/app-catalog/samples/wBasis/src/main/res-ext/navigation/nav_graph.xml b/app-catalog/samples/wBasis/src/main/res-ext/navigation/nav_graph.xml index 04bf302..00bc16c 100644 --- a/app-catalog/samples/wBasis/src/main/res-ext/navigation/nav_graph.xml +++ b/app-catalog/samples/wBasis/src/main/res-ext/navigation/nav_graph.xml @@ -1,5 +1,4 @@ - - - + android:orientation="vertical"> + + android:layout_weight="1" + android:padding="16dp" + android:text="@string/gesture_intro_message" /> + + android:background="@android:color/darker_gray" /> + + android:layout_height="0dp" + android:layout_weight="1" /> \ No newline at end of file diff --git a/app-catalog/samples/wBasis/src/main/res-ext/menu/gesture_main.xml b/app-catalog/samples/wBasis/src/main/res-gesture/menu/gesture_main.xml similarity index 86% rename from app-catalog/samples/wBasis/src/main/res-ext/menu/gesture_main.xml rename to app-catalog/samples/wBasis/src/main/res-gesture/menu/gesture_main.xml index d1b049f..5292be0 100644 --- a/app-catalog/samples/wBasis/src/main/res-ext/menu/gesture_main.xml +++ b/app-catalog/samples/wBasis/src/main/res-gesture/menu/gesture_main.xml @@ -1,5 +1,4 @@ - - + + + + + + \ No newline at end of file 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..8f45dd9 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/drawable/oval.xml @@ -0,0 +1,19 @@ + + + + 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 0000000..1358628 Binary files /dev/null and b/app-catalog/samples/wBasis/src/main/res-transition/drawable/tile.9.png differ diff --git a/app-catalog/samples/wBasis/src/main/res-transition/drawable/transition_ic_launcher.png b/app-catalog/samples/wBasis/src/main/res-transition/drawable/transition_ic_launcher.png new file mode 100644 index 0000000..cf93e69 Binary files /dev/null and b/app-catalog/samples/wBasis/src/main/res-transition/drawable/transition_ic_launcher.png differ diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout-w720dp/activity_basic_transition.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout-w720dp/activity_basic_transition.xml new file mode 100755 index 0000000..e6eff6b --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout-w720dp/activity_basic_transition.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + 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..cd5306b --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout-w720dp/activity_custom_transition.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app-catalog/samples/wBasis/src/main/res-transition/layout/activity_basic_transition.xml b/app-catalog/samples/wBasis/src/main/res-transition/layout/activity_basic_transition.xml new file mode 100755 index 0000000..24db1f6 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/activity_basic_transition.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + 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..dc596ab --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/activity_custom_transition.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + 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..d357bd5 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene1.xml @@ -0,0 +1,45 @@ + + + + + + + + + + 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..460f505 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene2.xml @@ -0,0 +1,45 @@ + + + + + + + + + + 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..3560e1d --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/custom_scene3.xml @@ -0,0 +1,45 @@ + + + + + + + + + + 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..8af3a48 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/fragment_basic_transition.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file 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..dfbefa7 --- /dev/null +++ b/app-catalog/samples/wBasis/src/main/res-transition/layout/fragment_custom_transition.xml @@ -0,0 +1,35 @@ + + + +