国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

[MAUI程序設(shè)計] 用Handler實現(xiàn)自定義跨平臺控件

這篇具有很好參考價值的文章主要介紹了[MAUI程序設(shè)計] 用Handler實現(xiàn)自定義跨平臺控件。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

@

目錄
  • Handler
  • 與Xamarin.Forms實現(xiàn)的區(qū)別
  • 為什么要用Handler代替Renderer
    • 解耦
    • 生命周期管理
    • 更細(xì)粒度的控制
  • 用Effect來實現(xiàn)呢?
  • 自定義手勢監(jiān)聽控件
  • 在各平臺上實現(xiàn)TouchRecognizer
    • iOS中的實現(xiàn)
    • Android中的實現(xiàn)
    • Windows中的實現(xiàn)
  • 創(chuàng)建控件
  • 使用控件
  • 最終效果
  • 項目地址

今天來談一談MAUI跨平臺技術(shù)的核心概念——跨平臺控件。

無論是MAUI,Xamarin.Forms還是其它的跨平臺技術(shù),他們是多個不同平臺功能的抽象層,利用通用的方法實現(xiàn)所謂“一次開發(fā),處處運行”。

跨平臺框架需要考慮通用方法在各平臺的兼容,但由于各原生平臺(官方將原生稱為本機)功能的差異,可能不能滿足特定平臺的所有功能。

比如,眾所周知,MAUI的手勢識別器沒有提供長按(LongPress)手勢的識別, TapGestureRecognizer也僅僅是按下和抬起的識別,沒有提供長按的識別。

這時候就需要開發(fā)者自己實現(xiàn)特定平臺的功能,這就是自定義控件。

要想重寫控件,或增強默認(rèn)控件的功能或視覺效果,最基礎(chǔ)的功能就是要拿到跨平臺控件,和本機控件。

通過跨平臺控件定義的屬性傳遞到本機控件,在本機控件中響應(yīng)和處理自定義屬性的變化。達(dá)到自定義控件的目的。

接下來介紹在MAUI新增的特性:控制器(Handler),好用但知道的人不多 。

Handler

因為跨平臺控件的實現(xiàn)由本機視圖在每個平臺上提供的,MAUI為每個控件創(chuàng)建了接口用于抽象控件。 實現(xiàn)這些接口的跨平臺控件稱為 虛擬視圖。 處理程序 將這些虛擬視圖映射到每個平臺上的控件,這些控件稱為 本機視圖。

在VisualElement中的Handler對象是一個實現(xiàn)了IElementHandler接口的類,通過它可以訪問 虛擬視圖本機視圖。

public interface IViewHandler : IElementHandler
{
    bool HasContainer { get; set; }
    object? ContainerView { get; }
    IView? VirtualView { get; }

    Size GetDesiredSize(double widthConstraint, double heightConstraint);
    void PlatformArrange(Rect frame);
}

每個控件有各自的Handler以及接口,請查看官方文檔。

它可以通過注冊全局的映射器,作為特定本機平臺上實現(xiàn)自定義控件的功能的入口。
然后結(jié)合.NET 6 條件編譯的語言特性,可以更加方便在但文件上,為每個平臺編寫自定義處理程序。

Entry是實現(xiàn)IEntry接口的單行文本輸入控件,它對應(yīng)的Handler是EntryHandler。

[MAUI程序設(shè)計] 用Handler實現(xiàn)自定義跨平臺控件

如果我們想要在Entry控件獲取焦點時,自動全選文本。

  Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
        {
#if ANDROID
            handler.PlatformView.SetSelectAllOnFocus(true);
#elif IOS || MACCATALYST
            handler.PlatformView.EditingDidBegin += (s, e) =>
            {
                handler.PlatformView.PerformSelector(new ObjCRuntime.Selector("selectAll"), null, 0.0f);
            };
#elif WINDOWS
            handler.PlatformView.GotFocus += (s, e) =>
            {
                handler.PlatformView.SelectAll();
            };
#endif
        });

或者,可以使用分部類將代碼組織到特定于平臺的文件夾和文件中。 有關(guān)條件編譯的詳細(xì)信息,請參考官方文檔。

與Xamarin.Forms實現(xiàn)的區(qū)別

在Xamarin.Forms時代,已經(jīng)提供了一套自定義控件的機制,呈現(xiàn)器(Renderer)。

Xamarin.Forms的控件,比如Entry是通過在封裝于特定平臺下的EntryRenderer的類中渲染的。

[MAUI程序設(shè)計] 用Handler實現(xiàn)自定義跨平臺控件

通過重寫控件默認(rèn)Renderer,可以完全改變控件的外觀和行為方式。

  • Element,Xamarin.Forms 元素
  • Control,本機視圖、小組件或控件對象

為什么要用Handler代替Renderer

雖然Renderer功能非常強大,但是絕大部分場景來說,不是每次都需要重寫控件,而僅僅是給控件添加一些特定平臺的增強功能,如果還需要重寫OnElementPropertyChanged 將跨平臺控件的屬性值傳輸?shù)奖緳C控件,這種方式太過于復(fù)雜。

以我的理解,Handler是對Renderer的一種優(yōu)化,它解決了Renderer的這些問題:Renderer和跨平臺控件的耦合,對自定義控件的生命周期管理,和對自定義控件的更細(xì)粒度控制。

解耦

在Xamarin.Froms的Render中,要想拿到跨平臺控件的屬性,需要通過直接引用跨平臺類型,這樣就導(dǎo)致了Renderer和跨平臺控件的耦合。

在MAUI中,處理程序會將平臺控件與框架分離。平臺控件只需處理框架的需求。這樣的好處是處理程序也適用于其他框架(如 Comet 和 Fabulous)重復(fù)使用。

生命周期管理

可以通過處理程序的映射器(Mapper)在應(yīng)用中的任意位置進(jìn)行處理程序自定義。 自定義處理程序后,它將影響在應(yīng)用中任意位置的該類型所有控件。

可以通過控件HandlerChanged 和HandlerChanging,管理Handler的生命周期,通過其參數(shù)可以獲取控件掛載、移除Handler的時機,可以在這里做一些初始化和清理工作。

更細(xì)粒度的控制

因為實現(xiàn)了全局映射器注冊,這樣的好處還有不用重寫子類控件,我們可以通過獲取跨平臺控件的某屬性,或注解屬性,拿到需要進(jìn)行處理的控件。實現(xiàn)自由的面向切面的過濾。

用Effect來實現(xiàn)呢?

或者我們僅僅想更改控件外觀,可以通過Effect來實現(xiàn)。但無論是Effect還是Renderer,他們只能是全局的,在需要狀態(tài)維護(hù)的業(yè)務(wù)邏輯中,比如長按,實際上是按下,抬起的過程,沒有按下的控件不要響應(yīng)抬起,正因為這樣要記錄哪些控件已經(jīng)按下,可能需要用一個字典維護(hù)所有的自定義控件。

而MAUI的自定義映射器實際上就是一個字典,減少了代碼的復(fù)雜度。

在MAUI中,官方建議遷移到Handler。Renderer雖仍然可以在MAUI中使用,但是它們屬于兼容方案(Compatibility命名空間),并且不提供ExportRenderer標(biāo)簽,需要在CreateMauiApp中手動添加:

.ConfigureMauiHandlers((handlers) =>
        {
#if ANDROID
            handlers.AddHandler(typeof(PressableView), typeof(XamarinCustomRenderer.Droid.Renderers.PressableViewRenderer));
#elif IOS
            handlers.AddHandler(typeof(PressableView), typeof(XamarinCustomRenderer.iOS.Renderers.PressableViewRenderer));
#endif
        });

從Renderer遷移到Handler的詳細(xì)步驟,請參考官方文檔

剛才說到,MAUI缺少長按的手勢控制,

所謂長按(LongPress),實際上是將手指接觸屏幕到離開屏幕的動作分解。當(dāng)手指接觸屏幕時,觸發(fā)按下(Pressed)事件,當(dāng)手指離開屏幕時,觸發(fā)抬起(Released)事件。如果在按下和抬起之間的時間間隔超過一定的時間,就認(rèn)為是長按。

對于這樣簡單的功能,MAUI團(tuán)隊并不打算將它加入到手勢識別中??赡軐⑦@個需求下放給社區(qū)來實現(xiàn),我在CommunityToolkit找到了這個issue(https://github.com/CommunityToolkit/Maui/issues/86)但是到目前為止,官方僅有的只是用Effect實現(xiàn)的手勢識別案例(https://docs.microsoft.com/xamarin/xamarin-forms/app-fundamentals/effects/touch-tracking)

那么我們參考這個官方案例,在MAUI上實現(xiàn)一個長按的手勢控制吧

自定義手勢監(jiān)聽控件

定義可以監(jiān)聽的手勢類別,分別是按下、移動、抬起、取消、進(jìn)入、退出


 public enum TouchActionType
    {
        Entered,
        Pressed,
        Moved,
        Released,
        Exited,
        Cancelled
    }

添加手勢監(jiān)聽器TouchRecognizer,它將提供一個事件OnTouchActionInvoked,用觸發(fā)手勢動作。

public partial class TouchRecognizer: IDisposable
{
    public event EventHandler<TouchActionEventArgs> OnTouchActionInvoked;
    public partial void Dispose();
}

EventArg類TouchActionEventArgs,用于傳遞手勢動作的參數(shù)

public long Id { private set; get; }

public TouchActionType Type { private set; get; }

public Point Location { private set; get; }

public bool IsInContact { private set; get; }

在各平臺上實現(xiàn)TouchRecognizer

使用分布類(partial class)的方式,創(chuàng)建TouchRecognizer.iOS.cs、TouchRecognizer.Android.csTouchRecognizer.Windows.cs文件,分別在各平臺上實現(xiàn)TouchRecognizer。在各平臺上的實現(xiàn)代碼不會混在一起,便于維護(hù)。

iOS中的實現(xiàn)

public partial class TouchRecognizer : UIGestureRecognizer, IDisposable
{
    UIView iosView;

    public TouchRecognizer(UIView view)
    {
        this.iosView = view;
    }

    public override void TouchesBegan(NSSet touches, UIEvent evt)
    {
        base.TouchesBegan(touches, evt);

        foreach (UITouch touch in touches.Cast<UITouch>())
        {
            long id = touch.Handle.Handle.ToInt64();
            InvokeTouchActionEvent(this, id, TouchActionType.Pressed, touch, true);
        }


    }

    public override void TouchesMoved(NSSet touches, UIEvent evt)
    {
        base.TouchesMoved(touches, evt);

        foreach (UITouch touch in touches.Cast<UITouch>())
        {
            long id = touch.Handle.Handle.ToInt64();

            InvokeTouchActionEvent(this, id, TouchActionType.Moved, touch, true);

        }
    }

    public override void TouchesEnded(NSSet touches, UIEvent evt)
    {
        base.TouchesEnded(touches, evt);

        foreach (UITouch touch in touches.Cast<UITouch>())
        {
            long id = touch.Handle.Handle.ToInt64();

            InvokeTouchActionEvent(this, id, TouchActionType.Released, touch, false);

        }
    }

    public override void TouchesCancelled(NSSet touches, UIEvent evt)
    {
        base.TouchesCancelled(touches, evt);

        foreach (UITouch touch in touches.Cast<UITouch>())
        {
            long id = touch.Handle.Handle.ToInt64();

            InvokeTouchActionEvent(this, id, TouchActionType.Cancelled, touch, false);

        }
    }


    void InvokeTouchActionEvent(TouchRecognizer recognizer, long id, TouchActionType actionType, UITouch touch, bool isInContact)
    {
        var cgPoint = touch.LocationInView(recognizer.View);
        var xfPoint = new Point(cgPoint.X, cgPoint.Y);
        OnTouchActionInvoked?.Invoke(this, new TouchActionEventArgs(id, actionType, xfPoint, isInContact));
    }
}

Android中的實現(xiàn)

public partial class TouchRecognizer : IDisposable
{
    Android.Views.View androidView;
    Func<double, double> fromPixels;
    int[] twoIntArray = new int[2];
    private Point _oldscreenPointerCoords;

    public TouchRecognizer(Android.Views.View view)
    {
        this.androidView = view;
        if (view != null)
        {
            fromPixels = view.Context.FromPixels;
            view.Touch += OnTouch;
        }
    }

    public partial void Dispose()
    {
        androidView.Touch -= OnTouch;
    }

    void OnTouch(object sender, Android.Views.View.TouchEventArgs args)
    {
        var senderView = sender as Android.Views.View;
        var motionEvent = args.Event;
        var pointerIndex = motionEvent.ActionIndex;
        var id = motionEvent.GetPointerId(pointerIndex);
        senderView.GetLocationOnScreen(twoIntArray);
        var screenPointerCoords = new Point(twoIntArray[0] + motionEvent.GetX(pointerIndex),
                                                twoIntArray[1] + motionEvent.GetY(pointerIndex));


        switch (args.Event.ActionMasked)
        {
            case MotionEventActions.Down:
            case MotionEventActions.PointerDown:
                InvokeTouchActionEvent(this, id, TouchActionType.Pressed, screenPointerCoords, true);
                break;

            case MotionEventActions.Move:
                for (pointerIndex = 0; pointerIndex < motionEvent.PointerCount; pointerIndex++)
                {
                    id = motionEvent.GetPointerId(pointerIndex);


                    senderView.GetLocationOnScreen(twoIntArray);

                    screenPointerCoords = new Point(twoIntArray[0] + motionEvent.GetX(pointerIndex),
                                                    twoIntArray[1] + motionEvent.GetY(pointerIndex));


                    if (IsOutPit(senderView, screenPointerCoords))
                    {
                        if (_oldscreenPointerCoords != default)
                        {
                            InvokeTouchActionEvent(this, id, TouchActionType.Exited, screenPointerCoords, true);
                            _oldscreenPointerCoords=default;
                        }

                    }
                    else
                    {
                        if (_oldscreenPointerCoords == default
                                                    ||screenPointerCoords!= _oldscreenPointerCoords)
                        {
                            _oldscreenPointerCoords=screenPointerCoords;
                            InvokeTouchActionEvent(this, id, TouchActionType.Moved, screenPointerCoords, true);
                        }
                    }


                }
                break;

            case MotionEventActions.Up:
            case MotionEventActions.Pointer1Up:
                InvokeTouchActionEvent(this, id, TouchActionType.Released, screenPointerCoords, false);
                break;

            case MotionEventActions.Cancel:

                InvokeTouchActionEvent(this, id, TouchActionType.Cancelled, screenPointerCoords, false);
                break;
        }
    }

    private bool IsOutPit(Android.Views.View senderView, Point screenPointerCoords)
    {
        return (screenPointerCoords.X<twoIntArray[0]||screenPointerCoords.Y<twoIntArray[1])
                                    ||(screenPointerCoords.X>twoIntArray[0]+senderView.Width||screenPointerCoords.Y>twoIntArray[1]+senderView.Height);
    }

    void InvokeTouchActionEvent(TouchRecognizer touchEffect, int id, TouchActionType actionType, Point pointerLocation, bool isInContact)
    {
        touchEffect.androidView.GetLocationOnScreen(twoIntArray);
        double x = pointerLocation.X - twoIntArray[0];
        double y = pointerLocation.Y - twoIntArray[1];
        var point = new Point(fromPixels(x), fromPixels(y));
        OnTouchActionInvoked?.Invoke(this, new TouchActionEventArgs(id, actionType, point, isInContact));
    }

}

Windows中的實現(xiàn)

public partial class TouchRecognizer : IDisposable
{
    FrameworkElement windowsView;

    public TouchRecognizer(FrameworkElement view)
    {
        this.windowsView = view;
        if (this.windowsView != null)
        {
            this.windowsView.PointerEntered += View_PointerEntered;
            this.windowsView.PointerPressed += View_PointerPressed;
            this.windowsView.Tapped +=View_Tapped;
            this.windowsView.PointerMoved += View_PointerMoved;
            this.windowsView.PointerReleased += View_PointerReleased;
            this.windowsView.PointerExited += View_PointerExited;
            this.windowsView.PointerCanceled += View_PointerCancelled;
        }
    }

    public partial void Dispose()
    {
        windowsView.PointerEntered -= View_PointerEntered;
        windowsView.PointerPressed -= View_PointerPressed;
        windowsView.Tapped -=View_Tapped;
        windowsView.PointerMoved -= View_PointerMoved;
        windowsView.PointerReleased -= View_PointerReleased;
        windowsView.PointerExited -= View_PointerEntered;
        windowsView.PointerCanceled -= View_PointerCancelled;
    }
    private void View_Tapped(object sender, TappedRoutedEventArgs args)
    {
        //var windowsPoint = args.GetPosition(sender as UIElement);
        //Point point = new Point(windowsPoint.X, windowsPoint.Y);
        //InvokeTouchActionEvent(TouchActionType.Pressed, point, 0, true);

    }
    private void View_PointerEntered(object sender, PointerRoutedEventArgs args)
    {
        Point point = GetPoint(sender, args);
        var id = args.Pointer.PointerId;
        var isInContact = args.Pointer.IsInContact;
        InvokeTouchActionEvent(TouchActionType.Entered, point, id, isInContact);
    }

    private void View_PointerPressed(object sender, PointerRoutedEventArgs args)
    {
        Point point = GetPoint(sender, args);
        var id = args.Pointer.PointerId;
        var isInContact = args.Pointer.IsInContact;
        InvokeTouchActionEvent(TouchActionType.Pressed, point, id, isInContact);
        (sender as FrameworkElement).CapturePointer(args.Pointer);
    }

    private void View_PointerMoved(object sender, PointerRoutedEventArgs args)
    {
        Point point = GetPoint(sender, args);
        var id = args.Pointer.PointerId;
        var isInContact = args.Pointer.IsInContact;
        InvokeTouchActionEvent(TouchActionType.Moved, point, id, isInContact);
    }

    private void View_PointerReleased(object sender, PointerRoutedEventArgs args)
    {
        Point point = GetPoint(sender, args);
        var id = args.Pointer.PointerId;
        var isInContact = args.Pointer.IsInContact;
        InvokeTouchActionEvent(TouchActionType.Released, point, id, isInContact);
    }

    private void View_PointerExited(object sender, PointerRoutedEventArgs args)
    {
        Point point = GetPoint(sender, args);
        var id = args.Pointer.PointerId;
        var isInContact = args.Pointer.IsInContact;
        InvokeTouchActionEvent(TouchActionType.Exited, point, id, isInContact);
    }

    private void View_PointerCancelled(object sender, PointerRoutedEventArgs args)
    {
        Point point = GetPoint(sender, args);
        var id = args.Pointer.PointerId;
        var isInContact = args.Pointer.IsInContact;
        InvokeTouchActionEvent(TouchActionType.Cancelled, point, id, isInContact);
    }

    private void InvokeTouchActionEvent(TouchActionType touchActionType, Point point, uint id, bool isInContact)
    {
        OnTouchActionInvoked?.Invoke(this, new TouchActionEventArgs(id, touchActionType, point, isInContact));

    }

    private static Point GetPoint(object sender, PointerRoutedEventArgs args)
    {
        var pointerPoint = args.GetCurrentPoint(sender as UIElement);
        Windows.Foundation.Point windowsPoint = pointerPoint.Position;
        Point point = new Point(windowsPoint.X, windowsPoint.Y);
        return point;
    }
}

創(chuàng)建控件

創(chuàng)建手勢監(jiān)聽控件TouchContentView,它繼承于ContentView。

注意:盡量避免在構(gòu)造函數(shù)中調(diào)用ViewHandler.ViewMapper.AppendToMapping,它將導(dǎo)致從頁面的XAML根元素開始,遞歸遍歷所有IView虛擬視圖子元素,將其添加到ViewMapper中

我們用HandlerChanging監(jiān)聽Handler改變,當(dāng)OldHandler屬性不為空時,表示即將從跨平臺控件中刪除現(xiàn)有的本機控件,此時我們需要將TouchRecognizer移除,以免內(nèi)存泄漏。

public class TouchContentView : ContentView
{
    private TouchRecognizer touchRecognizer;

    public event EventHandler<TouchActionEventArgs> OnTouchActionInvoked;



    public TouchContentView()
    {
        this.HandlerChanged+=TouchContentView_HandlerChanged;
        this.HandlerChanging+=TouchContentView_HandlerChanging;
    }


    private void TouchContentView_HandlerChanged(object sender, EventArgs e)
    {

        var handler = this.Handler;
        if (handler != null)
        {
#if WINDOWS
            touchRecognizer = new TouchRecognizer(handler.PlatformView as Microsoft.UI.Xaml.FrameworkElement);
            touchRecognizer.OnTouchActionInvoked += TouchRecognizer_OnTouchActionInvoked;
#endif
#if ANDROID
            touchRecognizer = new TouchRecognizer(handler.PlatformView as Android.Views.View);
            touchRecognizer.OnTouchActionInvoked += TouchRecognizer_OnTouchActionInvoked;

#endif

#if IOS|| MACCATALYST
            touchRecognizer = new TouchRecognizer(handler.PlatformView as UIKit.UIView);
            touchRecognizer.OnTouchActionInvoked += TouchRecognizer_OnTouchActionInvoked;

            (handler.PlatformView as UIKit.UIView).UserInteractionEnabled = true;
            (handler.PlatformView as UIKit.UIView).AddGestureRecognizer(touchRecognizer);
#endif
        }

    }

    private void TouchContentView_HandlerChanging(object sender, HandlerChangingEventArgs e)
    {


        if (e.OldHandler != null)
        {
            var handler = e.OldHandler;

#if WINDOWS
            touchRecognizer.OnTouchActionInvoked -= TouchRecognizer_OnTouchActionInvoked;
#endif
#if ANDROID
            touchRecognizer.OnTouchActionInvoked -= TouchRecognizer_OnTouchActionInvoked;

#endif

#if IOS|| MACCATALYST
            touchRecognizer.OnTouchActionInvoked -= TouchRecognizer_OnTouchActionInvoked;

            (handler.PlatformView as UIKit.UIView).UserInteractionEnabled = false;
            (handler.PlatformView as UIKit.UIView).RemoveGestureRecognizer(touchRecognizer);
#endif


        }
    }

    private void TouchRecognizer_OnTouchActionInvoked(object sender, TouchActionEventArgs e)
    {
        OnTouchActionInvoked?.Invoke(this, e);
        Debug.WriteLine(e.Type + " is Invoked, position:" + e.Location);
    }
}

使用控件

在Xaml中引用TouchContentView所在的命名空間

xmlns:controls="clr-namespace:Lession2.TouchRecognizer;assembly=Lession2"

將你的控件放在TouchContentView中,然后監(jiān)聽TouchContentView的OnTouchActionInvoked事件即可。
注意:對于Button這樣的點擊控件,點擊事件不會向下傳遞,因此如果包裹了Button,那么OnTouchActionInvoked事件將不會被觸發(fā)。

<controls:TouchContentView Style="{StaticResource HoldDownButtonStyle}"
                            
                            Grid.Column="0"
                            OnTouchActionInvoked="TouchContentView_OnTouchActionInvoked">
    <BoxView CornerRadius="10" Color="Red"></BoxView>

</controls:TouchContentView>


<controls:TouchContentView Style="{StaticResource HoldDownButtonStyle}"

                            Grid.Column="1"
                            OnTouchActionInvoked="TouchContentView_OnTouchActionInvoked">
    <Image Source="./dotnet_bot.svg"></Image>

</controls:TouchContentView>


<controls:TouchContentView Style="{StaticResource HoldDownButtonStyle}"

                            Grid.Column="2"
                            OnTouchActionInvoked="TouchContentView_OnTouchActionInvoked">
    <Label Text="假裝我是一個按鈕"></Label>

</controls:TouchContentView>

最終效果

在控件中將應(yīng)用手勢監(jiān)聽。

[MAUI程序設(shè)計] 用Handler實現(xiàn)自定義跨平臺控件

項目地址

Github:maui-learning文章來源地址http://www.zghlxwxcb.cn/news/detail-470935.html

到了這里,關(guān)于[MAUI程序設(shè)計] 用Handler實現(xiàn)自定義跨平臺控件的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 計算機程序設(shè)計-第4周(函數(shù)定義和調(diào)用)

    本關(guān)任務(wù):定義一個函數(shù)isPrimeNumber,傳入一個整數(shù)參數(shù)n,判斷n是否為素數(shù),返回判斷結(jié)果。 然后編寫主函數(shù),對該函數(shù)功能進(jìn)行測試,要求用戶輸入一個正整數(shù),根據(jù)isPrimeNumber的返回值輸出對應(yīng)結(jié)果:是素數(shù)則輸出“是素數(shù)”,不是素數(shù)則輸出“不是素數(shù)”。

    2024年02月06日
    瀏覽(19)
  • Python 程序設(shè)計入門(023)—— Python 的自定義函數(shù)

    在 Python 中,函數(shù)的應(yīng)用非常廣泛。比如:input()、print()、str()、range()、len() 等,這些稱為 Python 的內(nèi)置函數(shù),可以直接使用。Python 支持自定義函數(shù),即將一段有規(guī)律的、可重復(fù)使用的代碼定義為函數(shù),達(dá)到一次編寫,多次使用的目的。 自定義函數(shù)使用 def 實現(xiàn),語法格

    2024年02月12日
    瀏覽(21)
  • 頭歌Educoder實驗:程序設(shè)計二(面向?qū)ο螅實訓(xùn)3_類外定義成員函數(shù)

    第1關(guān):類外定義存取函數(shù) 任務(wù)描述 本關(guān)仍然有一個 Int 類,該類包含一個 int 類型的成員。為其編寫存取函數(shù)。注意,存取函數(shù)要在類外實現(xiàn)。 相關(guān)知識 類的定義中,既可以書寫成員函數(shù)的聲明,也可以書寫成員函數(shù)的定義(即實現(xiàn))。如果在類中定義成員函數(shù),則該成員

    2024年02月06日
    瀏覽(29)
  • [MAUI]寫一個跨平臺富文本編輯器

    [MAUI]寫一個跨平臺富文本編輯器

    @ 目錄 原理 創(chuàng)建編輯器 定義 實現(xiàn)復(fù)合樣式 選擇范圍 字號 字體顏色與背景色 字體下劃線 字體加粗與斜體 序列化和反序列化 跨平臺實現(xiàn) 集成至編輯器 創(chuàng)建控件 使用控件 最終效果 已知問題 項目地址 富文本編輯器是一種所見即所得(what you see is what you get 簡稱 WYSIWYG)文本編

    2024年02月08日
    瀏覽(29)
  • (微信小程序畢業(yè)設(shè)計)校園圈子小程序的設(shè)計與實現(xiàn)(附源碼+論文)

    (微信小程序畢業(yè)設(shè)計)校園圈子小程序的設(shè)計與實現(xiàn)(附源碼+論文)

    大家好!我是島上程序猿,感謝您閱讀本文,歡迎一鍵三連哦。 ??當(dāng)前專欄:微信小程序畢業(yè)設(shè)計 精彩專欄推薦???????????? ?? 安卓app畢業(yè)設(shè)計 ??Java畢業(yè)設(shè)計 目前各個高?;径加懈髯缘纳鐓^(qū),但仍以傳統(tǒng)的BBS、論壇等形式為主,移動互聯(lián)網(wǎng)形式下,多以班級、社

    2024年02月08日
    瀏覽(24)
  • 澡堂洗澡預(yù)約小程序小程序系統(tǒng)設(shè)計與實現(xiàn)

    澡堂洗澡預(yù)約小程序小程序系統(tǒng)設(shè)計與實現(xiàn)

    目的 :本課題主要目標(biāo)是設(shè)計并能夠?qū)崿F(xiàn)一個基于微信小程序預(yù)約訂座小程序,前臺用戶使用小程序,后臺管理使用基PHP+MySql的B/S架構(gòu);通過后臺添加浴室類型、浴室房間,用戶通過小程序登錄,查看浴室、提交浴室預(yù)約信息。 意義 :微信小程序預(yù)約訂座小程序系統(tǒng)是計算

    2024年02月10日
    瀏覽(19)
  • 微信小程序畢業(yè)設(shè)計作品成品(03)在線投票小程序投票評選小程序系統(tǒng)設(shè)計與實現(xiàn)

    微信小程序畢業(yè)設(shè)計作品成品(03)在線投票小程序投票評選小程序系統(tǒng)設(shè)計與實現(xiàn)

    博主介紹 :《Vue.js入門與商城開發(fā)實戰(zhàn)》《微信小程序商城開發(fā)》圖書作者,CSDN博客專家,在線教育專家,CSDN鉆石講師;專注大學(xué)生畢業(yè)設(shè)計教育和輔導(dǎo)。 所有項目都配有從入門到精通的基礎(chǔ)知識視頻課程,免費 項目配有對應(yīng)開發(fā)文檔、開題報告、任務(wù)書、PPT、論文模版

    2024年02月08日
    瀏覽(14)
  • 微信小程序校園洗衣小程序系統(tǒng)設(shè)計與實現(xiàn)

    微信小程序校園洗衣小程序系統(tǒng)設(shè)計與實現(xiàn)

    ?博主介紹 :黃菊華老師《Vue.js入門與商城開發(fā)實戰(zhàn)》《微信小程序商城開發(fā)》圖書作者,CSDN博客專家,在線教育專家,CSDN鉆石講師;專注大學(xué)生畢業(yè)設(shè)計教育和輔導(dǎo)。 所有項目都配有從入門到精通的基礎(chǔ)知識視頻課程,免費 項目配有對應(yīng)開發(fā)文檔、開題報告、任務(wù)書、

    2024年02月04日
    瀏覽(26)
  • 微信小程序畢業(yè)設(shè)計作品成品(40)微信小程序茶葉商城系統(tǒng)設(shè)計與實現(xiàn)

    微信小程序畢業(yè)設(shè)計作品成品(40)微信小程序茶葉商城系統(tǒng)設(shè)計與實現(xiàn)

    博主介紹: 《Vue.js入門與商城開發(fā)實戰(zhàn)》《微信小程序商城開發(fā)》圖書作者,CSDN博客專家,在線教育專家,CSDN鉆石講師;專注大學(xué)生畢業(yè)設(shè)計教育和輔導(dǎo)。 所有項目都配有從入門到精通的基礎(chǔ)知識視頻課程,免費 項目配有對應(yīng)開發(fā)文檔、開題報告、任務(wù)書、PPT、論文模版

    2024年02月08日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包