我知道可以使用 SecureTextEntry
属性为 UITextFields
实现密码样式效果,我还在网上找到了一些代码来实现隐藏/显示密码效果 here ,但这仅适用于 UITextFields
,我需要为自定义 UITextView
实现相同的功能。我目前有一些代码可以实现为 UI 添加图像,但实际的显示/隐藏密码效果并未实现。
我在 Swift
here 中找到了一些如何执行此操作的代码,但我从未使用过 Swift
并且希望熟悉 Swift 的人
可以为我将其转换为 C#
,因为这可能是我需要的解决方案。
我还了解到,当 SecureTextEntry
属性设置为 true (即防止复制和转换字符成黑点),它仅在为 UITextViews
设置为 true 时阻止复制文本。这是我从这个属性 here 的文档中找到的
这是我目前在我的文件中实现显示/隐藏密码效果的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ResolutionGroupName("Xamarin")]
[assembly:ExportEffect(typeof(MyApp.iOS.CustomRenderers.PasswordEffect), "PasswordEffect")]
namespace MyApp.iOS.CustomRenderers
{
public class PasswordEffect : PlatformEffect
{
protected override void OnAttached()
{
Configure();
}
protected override void OnDetached()
{
//do nothing
}
private void Configure()
{
if (Control != null)
{
if (Control is UITextView) {
UITextView vUpdatedEntry = (UITextView)Control;
var buttonRect = UIButton.FromType(UIButtonType.Custom);
buttonRect.SetImage(UIImage.FromBundle("eye_image"), UIControlState.Normal);
buttonRect.TouchUpInside += (object sender, EventArgs e1) => {
if (vUpdatedEntry.SecureTextEntry)
{
vUpdatedEntry.SecureTextEntry = false;
buttonRect.SetImage(UIImage.FromBundle("eye_crossed_image"), UIControlState.Normal);
}
else
{
vUpdatedEntry.SecureTextEntry = true;
buttonRect.SetImage(UIImage.FromBundle("eye_image"), UIControlState.Normal);
}
};
// Would love to have password effect here :)
vUpdatedEntry.ShouldChangeText += (textField, range, replacementString) => {
string text = vUpdatedEntry.Text;
var result = text.Substring(0, (int)range.Location) + replacementString + text.Substring((int)range.Location + (int)range.Length);
vUpdatedEntry.Text = result;
return false;
};
buttonRect.Frame = new CoreGraphics.CGRect(10.0f, 0.0f, 15.0f, 15.0f);
buttonRect.ContentMode = UIViewContentMode.ScaleToFill;
UIView paddingViewRight = new UIView(new System.Drawing.RectangleF(0.0f, 0.0f, 30.0f, 18.0f));
paddingViewRight.AddSubview(buttonRect);
buttonRect.TranslatesAutoresizingMaskIntoConstraints = false;
buttonRect.CenterYAnchor.ConstraintEqualTo(paddingViewRight.CenterYAnchor).Active = true;
vUpdatedEntry.TextContainerInset = new UIEdgeInsets(8.0f, 0.0f, 8.0f, paddingViewRight.Frame.Width+5.0f);
vUpdatedEntry.AddSubview(paddingViewRight);
paddingViewRight.TranslatesAutoresizingMaskIntoConstraints = false;
paddingViewRight.TrailingAnchor.ConstraintEqualTo(vUpdatedEntry.LayoutMarginsGuide.TrailingAnchor, 9.0f).Active = true;
paddingViewRight.HeightAnchor.ConstraintEqualTo(vUpdatedEntry.HeightAnchor).Active = true;
paddingViewRight.WidthAnchor.ConstraintEqualTo(buttonRect.WidthAnchor,1.0f, 0.0f).Active = true;
Control.Layer.CornerRadius = 4;
Control.Layer.BorderColor = new CoreGraphics.CGColor(255, 255, 255);
Control.Layer.MasksToBounds = true;
vUpdatedEntry.TextAlignment = UITextAlignment.Left;
}
}
}
}
}
最佳答案
你可以定义一个自定义的UITextViewDelegate
来实现它。
public class TextViewDelegate : UITextViewDelegate
{
private UITextView myTextView;
bool secureTextViewEntry; // default is NO
NSMutableString secureText;
NSTimer timer;
NSString lastText;
public TextViewDelegate(UITextView myTextView)
{
this.myTextView = myTextView;
secureTextViewEntry = false;
secureText = new NSMutableString();
}
public override bool ShouldChangeText(UITextView textView, NSRange range, string text)
{
if("\n" == text)
{
textView.ResignFirstResponder();
return false;
}
lastText = new NSString(text);
return true;
//return base.ShouldChangeText(textView, range, text);
}
public override void Changed(UITextView textView)
{
Console.WriteLine("-----" + secureText);
if (secureTextViewEntry)
{
string text = textView.Text;
if(text.Length > 0)
{
if("" == lastText)
{
secureText.DeleteCharacters(new NSRange(secureText.Length - 1, 1));
onlyPassword();
if (null != timer)
{
timer.Invalidate();
}
//base.Changed(textView);
return;
}
else
{
NSString one = new NSString(text.Substring(text.Length - 1));
secureText.Append(one);
NSMutableString temp = new NSMutableString();
for (int i = 0; i < secureText.Length - 1; i++)
{
temp.Append(new NSString("•"));
}
temp.Append(new NSString(secureText.ToString().Substring(secureText.ToString().Length - 1)));
myTextView.Text = temp;
if (null != timer)
{
timer.Invalidate();
}
timer =NSTimer.CreateScheduledTimer(2, onlyPassword);
}
}
else
{
secureText = new NSMutableString();
}
//base.Changed(textView);
}
else {
if (textView.Text.Length == 0)
{
secureText = new NSMutableString();
}
else
{
secureText = new NSMutableString();
secureText.SetString(new NSString(textView.Text));
}
if(null != timer) {
timer.Invalidate();
}
//base.Changed(textView);
}
}
private void onlyPassword(NSTimer obj)
{
//throw new NotImplementedException();
onlyPassword();
}
private void onlyPassword()
{
//throw new NotImplementedException();
timer.Invalidate();
NSMutableString temp = new NSMutableString();
for(int i = 0; i< secureText.Length; i++)
{
temp.Append(new NSString("•"));
}
myTextView.Text = temp;
}
public override void DidChange(NSKeyValueChange changeKind, NSIndexSet indexes, NSString forKey)
{
base.DidChange(changeKind, indexes, forKey);
}
//set Secure be true or false
public void setSecureTextViewEntry(bool _secureTextViewEntry)
{
secureTextViewEntry = _secureTextViewEntry;
if (secureText.Length == 0)
{
return;
}
else
{
if (secureTextViewEntry)
{
//secret
NSMutableString aaa = new NSMutableString();
for (int i = 0; i < secureText.Length; i++)
{
aaa.Append(new NSString("•"));
}
myTextView.Text = aaa;
}else{
//real word
myTextView.Text = secureText;
if (null != timer)
{
timer.Invalidate();
}
}
}
Changed(myTextView);
}
public bool getSecureTextViewEntry()
{
return secureTextViewEntry;
}
}
在 View Controller 中:
TextViewDelegate textViewDelegate;
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
textViewDelegate = new TextViewDelegate(MyTextView);
MyTextView.Delegate = textViewDelegate; //MyTextView from StoryBoard
}
partial void SetTrueButton_TouchUpInside(UIButton sender)
{
textViewDelegate.setSecureTextViewEntry(true);
}
partial void SetFalseButton_TouchUpInside(UIButton sender)
{
textViewDelegate.setSecureTextViewEntry(false);
}
效果如下:
注意:代码仅供引用,代码中存在一些小问题需要完善。
关于c# - 如何在 Xamarin 中使用 UITextView 为 iOS 实现隐藏/显示密码样式体验?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58208781/