【问题标题】:Select a textView without select text inside?选择一个 textView 里面没有选择文本?
【发布时间】:2016-03-08 10:39:52
【问题描述】:

我在UITableViewCell 中有一个UITextViewUITextView 我希望是可选择的,但不是文本。当Menu Controller 出现并且我想执行复制操作时,复制里面的所有文本而不仅仅是一部分。

我想要类似信使应用的东西:

目前我有:

提前感谢您!

【问题讨论】:

  • 看来你在找UITableViewDelegatetableView:shouldShowMenuForRowAtIndexPath:方法
  • 这取决于您的实现,您可以禁用文本视图的交互并在其上添加自定义 UIMenu 操作并通过手势调用它们
  • @Larme 我认为这是不可能的,因为我在单元格中有两个文本视图,我忘了说。

标签: ios objective-c uitableview uitextview


【解决方案1】:

事实上,这并不容易,因为在路上会出现一些奇怪的东西,但我设法创建了一个自定义的。

步骤如下:

  1. 创建UITextView 的子类
  2. 覆盖canPerformAction: withSender:以过滤菜单的默认操作 弹出。
  3. 配置textView 以便无法编辑选择
  4. 编辑UIMenuController 提供菜单上的操作和按钮的项目
  5. 为每个UIMenuItem ****添加不同的选择器(这是因为选择器的发送者不是UIMenuItem,而是UIMenuController,这导致了另一件事。查看here了解更多信息。一个gist我为此)

代码

废话不多说,代码如下:

EBCustomTextView.h

//
//  EBCustomTextView.h
//  TestProject
//
//  Created by Erid Bardhaj on 3/8/16.
//  Copyright © 2016 Erid Bardhaj. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef NS_ENUM(NSInteger, EBCustomTextViewMenuAction) {
    EBCustomTextViewMenuActionCopy,
    EBCustomTextViewMenuActionDefine,
    EBCustomTextViewMenuActionRead
};

@class EBCustomTextView;
@protocol EBCustomTextViewMenuActionDelegate <NSObject>

- (void)customTextView:(EBCustomTextView *)textView didSelectMenuAction:(EBCustomTextViewMenuAction)action;

@end

@interface EBCustomTextView : UITextView

@property (weak, nonatomic) id<EBCustomTextViewMenuActionDelegate> menuActionDelegate;

@end

EBCustomTextView.m

//
//  EBCustomTextView.m
//  TestProject
//
//  Created by Erid Bardhaj on 3/8/16.
//  Copyright © 2016 Erid Bardhaj. All rights reserved.
//

#import "EBCustomTextView.h"

@implementation EBCustomTextView {
    EBCustomTextViewMenuAction currentAction;
}

- (void)awakeFromNib {
    [super awakeFromNib];

    // Configure the textView
    self.editable = NO;
    self.selectable = NO;
}

#pragma mark - Datasource

- (NSArray *)items {
    UIMenuItem *item = [[UIMenuItem alloc] initWithTitle:@"Copy" action:@selector(copyMenuItemPressed)];
    UIMenuItem *item1 = [[UIMenuItem alloc] initWithTitle:@"Define" action:@selector(defineMenuItemPressed)];
    UIMenuItem *item2 = [[UIMenuItem alloc] initWithTitle:@"Read" action:@selector(readMenuItemPressed)];

    return @[item, item1, item2];
}


#pragma mark - Actions

- (void)copyMenuItemPressed {
    if ([self.menuActionDelegate respondsToSelector:@selector(customTextView:didSelectMenuAction:)]) {
        [self.menuActionDelegate customTextView:self didSelectMenuAction:EBCustomTextViewMenuActionCopy];
    }
}

- (void)defineMenuItemPressed {
    if ([self.menuActionDelegate respondsToSelector:@selector(customTextView:didSelectMenuAction:)]) {
        [self.menuActionDelegate customTextView:self didSelectMenuAction:EBCustomTextViewMenuActionDefine];
    }
}

- (void)readMenuItemPressed {
    if ([self.menuActionDelegate respondsToSelector:@selector(customTextView:didSelectMenuAction:)]) {
        [self.menuActionDelegate customTextView:self didSelectMenuAction:EBCustomTextViewMenuActionRead];
    }
}

#pragma mark - Private

- (void)menuItemPressedAtIndex:(NSInteger)index {
    currentAction = index;

    if ([self.menuActionDelegate respondsToSelector:@selector(customTextView:didSelectMenuAction:)]) {
        [self.menuActionDelegate customTextView:self didSelectMenuAction:currentAction];
    }
}

#pragma mark Helpers

- (void)showMenuController {
    UIMenuController *theMenu = [UIMenuController sharedMenuController];
    theMenu.menuItems = [self items];
    [theMenu update];

    CGRect selectionRect = CGRectMake (0, 0, self.contentSize.width, self.contentSize.height);
    [theMenu setTargetRect:selectionRect inView:self];
    [theMenu setMenuVisible:(theMenu.isMenuVisible) ? NO : YES animated:YES];
}

#pragma mark - Overridings

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    // Filter any action for this textView except our custom ones
    if (action == @selector(copyMenuItemPressed) || action == @selector(defineMenuItemPressed) || action == @selector(readMenuItemPressed)) {
        return YES;
    }
    return NO;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *theTouch = [touches anyObject];

    if ([theTouch tapCount] == 1  && [self becomeFirstResponder]) {
        [self showMenuController];
    }
}


@end

实施

将你的 textView 的类设置为 EBCustomTextView 并符合 EBCustomTextViewMenuActionDelegate

界面

@interface ViewController () <EBCustomTextViewMenuActionDelegate>

viewDidLoad

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.textView.menuActionDelegate = self;
}

协议一致性

#pragma mark - Delegation

#pragma mark EBCustomTextViewMenuActionDelegate 

- (void)customTextView:(EBCustomTextView *)textView didSelectMenuAction:(EBCustomTextViewMenuAction)action {
    switch (action) {
        case EBCustomTextViewMenuActionCopy:
            NSLog(@"Copy Action");
            break;

        case EBCustomTextViewMenuActionRead:
            NSLog(@"Read Action");
            break;

        case EBCustomTextViewMenuActionDefine:
            NSLog(@"Define Action");
            break;

        default:
            break;
    }
}

输出

享受:)

【讨论】:

  • 谢谢,您的回答看起来非常好,但我已经解决了我的问题。我会将我的解决方案发布到!
【解决方案2】:

你必须使用

[UITextView selectAll:self];

或(具有特定范围)

UITextView.selectedRange = NSMakeRange(0, 5);

或添加txtview.delegate = self;

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
    dispatch_async(dispatch_get_main_queue(), ^{
        [textView selectAll:nil];  //nil or self as per needed
    });
    return YES;
}

【讨论】:

    【解决方案3】:

    使用 UILongPressGestureRecognizer 手势

    #import "ViewController.h"
    
    @interface ViewController ()<UIGestureRecognizerDelegate>
    {
       UITextView * txtV;
       UILongPressGestureRecognizer * longPressGestureRecognizer;
    }
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
       [super viewDidLoad];
    
       txtV=[[UITextView alloc]initWithFrame:CGRectMake(20, 50, 280, 300)];
       txtV.text = @"Jai Maharashtra";
       txtV.userInteractionEnabled=YES;
       txtV.selectable=NO;
       txtV.editable=NO;
       txtV.font= [UIFont italicSystemFontOfSize:[UIFont systemFontSize]];
       [self.view addSubview:txtV];
    
       longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGesture:)];
       longPressGestureRecognizer.delegate=self;
       [txtV addGestureRecognizer:longPressGestureRecognizer];
    }
    
    - (void)longPressGesture:(UILongPressGestureRecognizer *)gestureRecognizer
    {
        if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
        {
           txtV.selectable=YES;
           [txtV selectAll:self];
        }
    }
    
    -(BOOL)canPerformAction:(SEL)action withSender:(id)sender
    {
        [txtV selectAll:self];
    
        if (action == @selector(cut:))
        {
           return YES;
        }
        if (action == @selector(selectAll:))
        {
          return YES;
        }
        if (action == @selector(copy:))
        {
          return YES;
        }
        if (action == @selector(delete:))
        {
          return YES;
        }
    
        txtV.selectable=NO;
        return YES;
     }
    

    【讨论】:

      【解决方案4】:

      首先我开始为单元格中的每个UITextView 创建UILongPressGestureRecognizer 以识别长按。

      cellForRowAtIndexPath 中我只需添加该代码:

       UILongPressGestureRecognizer *recognizer1 = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleLongPressText1:)];
       messageRecognizer.delaysTouchesBegan = YES;
      
       UILongPressGestureRecognizer *recognizer2 = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleLongPressText2:)];
       translateRecognizer.delaysTouchesBegan = YES;
      
      
       [cell.backgroundViewText1 addGestureRecognizer:recognizer1];
       [cell.backgroundViewText2 addGestureRecognizer:recognizer2];
      

      我使用两个不同的选择器,因为我需要知道从单元格中获取哪些文本。

      方法之后:

          -(void)handleLongPressText1:(UILongPressGestureRecognizer *)gestureRecognizer
      {
          if ([gestureRecognizer state] == UIGestureRecognizerStateBegan) {
              CGPoint p = [gestureRecognizer locationInView:self.tableView];
              NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
              if (indexPath == nil){
                  NSLog(@"couldn't find index path");
              } else {
                  [self becomeFirstResponder];
      
                  UIMenuController *menuController = [UIMenuController sharedMenuController];
                  UIMenuItem *resetMenuItem = [[UIMenuItem alloc] initWithTitle:@"Copy" action:@selector(copyMethod)];
                  UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Read" action:@selector(readButtonAction)];
      
                  [menuController setMenuItems:[NSArray arrayWithObjects:resetMenuItem,menuItem, nil]];
                  CGRect rect =gestureRecognizer.view.frame;
                  NSLog(@"%@", NSStringFromCGRect(rect));
                  [menuController setTargetRect:gestureRecognizer.view.frame inView:[[gestureRecognizer view] superview]];
                  [menuController setMenuVisible:YES animated:YES];
      
              }
          }
      }
      
          -(void)handleLongPressText2:(UILongPressGestureRecognizer *)gestureRecognizer
      {
          if ([gestureRecognizer state] == UIGestureRecognizerStateBegan) {
              CGPoint p = [gestureRecognizer locationInView:self.tableView];
              NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
              if (indexPath == nil){
                  NSLog(@"couldn't find index path");
              } else {
                  [self becomeFirstResponder];
      
                  UIMenuController *menuController = [UIMenuController sharedMenuController];
                  UIMenuItem *resetMenuItem = [[UIMenuItem alloc] initWithTitle:@"Copy" action:@selector(copyMethod)];
                  UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Read" action:@selector(readButtonAction)];
      
                  [menuController setMenuItems:[NSArray arrayWithObjects:resetMenuItem,menuItem, nil]];
                  CGRect rect =gestureRecognizer.view.frame;
                  NSLog(@"%@", NSStringFromCGRect(rect));
                  [menuController setTargetRect:gestureRecognizer.view.frame inView:[[gestureRecognizer view] superview]];
                  [menuController setMenuVisible:YES animated:YES];
              }
          }
      }
      

      要禁用UIMenuController 中的所有默认项,请使用上述代码

      - (BOOL)canPerformAction:(SEL)iAction withSender:(id)iSender {
      SEL copySelector = NSSelectorFromString(@"copyMethod");
      SEL readSeletor = NSSelectorFromString(@"readButtonAction");
      
      if (iAction == copySelector) {
          return YES;
      }else if (iAction ==readSeletor){
          return YES;
      }else{
          return NO;
      }
      
      
      return NO;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-26
        • 2011-12-17
        • 1970-01-01
        • 2015-08-10
        • 2011-06-04
        • 2011-08-26
        • 2023-03-13
        相关资源
        最近更新 更多