작업 시트에 UI Picker View 및 버튼 추가 - 어떻게?
제 지원서는 다음 사항들을 작업 시트에 추가해야 합니다.
- UI 도구 모음
- UI 도구 모음의 버튼
- UIPicker 컨트롤
제 요구 사항을 이해하기 위해 이미지를 첨부했습니다.
어떻게 구현할 수 있는지 설명해 주시겠습니까?
하나 더 해결책:
도구 모음은 없지만 분할된 컨트롤(아이캔디)
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil]; [actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent]; CGRect pickerFrame = CGRectMake(0, 40, 0, 0); UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame]; pickerView.showsSelectionIndicator = YES; pickerView.dataSource = self; pickerView.delegate = self; [actionSheet addSubview:pickerView]; [pickerView release]; UISegmentedControl *closeButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:@"Close"]]; closeButton.momentary = YES; closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f); closeButton.segmentedControlStyle = UISegmentedControlStyleBar; closeButton.tintColor = [UIColor blackColor]; [closeButton addTarget:self action:@selector(dismissActionSheet:) forControlEvents:UIControlEventValueChanged]; [actionSheet addSubview:closeButton]; [closeButton release]; [actionSheet showInView:[[UIApplication sharedApplication] keyWindow]]; [actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
이 질문은 오래된 질문이지만, 제가 액션을 구성했다고 빠르게 언급하겠습니다.작업을 생성할 수 있는 편의 기능이 있는 SheetPicker 클래스한 줄로 UIPickerView가 표시된 시트입니다.이 질문에 대한 답변의 코드를 기반으로 합니다.
편집: 이제 DatePicker 및 DistancePicker 사용도 지원합니다.
업데이트:
이 버전은 더 이상 사용되지 않습니다. 액션 사용대신 SheetPicker-3.0.
네! 드디어 찾았어요.
버튼 클릭 이벤트에 다음 코드를 구현하여 질문 이미지에 주어진 대로 조치 시트를 팝업합니다.
UIActionSheet *aac = [[UIActionSheet alloc] initWithTitle:@"How many?"
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
UIDatePicker *theDatePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0.0, 44.0, 0.0, 0.0)];
if(IsDateSelected==YES)
{
theDatePicker.datePickerMode = UIDatePickerModeDate;
theDatePicker.maximumDate=[NSDate date];
}else {
theDatePicker.datePickerMode = UIDatePickerModeTime;
}
self.dtpicker = theDatePicker;
[theDatePicker release];
[dtpicker addTarget:self action:@selector(dateChanged) forControlEvents:UIControlEventValueChanged];
pickerDateToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
pickerDateToolbar.barStyle = UIBarStyleBlackOpaque;
[pickerDateToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(DatePickerDoneClick)];
[barItems addObject:doneBtn];
[pickerDateToolbar setItems:barItems animated:YES];
[aac addSubview:pickerDateToolbar];
[aac addSubview:dtpicker];
[aac showInView:self.view];
[aac setBounds:CGRectMake(0,0,320, 464)];
iOS 7용 업데이트
UIAction용 Apple 문서시트:UIActionSheet is not designed to be subclassed, nor should you add views to its hierarchy
작업의 내용을 사용자 지정하지 않는 것이 좋습니다.iOS 7에서 심각한 잘못된 컨텍스트 오류로 이어질 수 있기 때문에 시트.저는 이 문제를 해결하는 데 몇 시간밖에 걸리지 않았고 결국 다른 접근법을 취하기로 결정했습니다.작업 시트를 보여주기 위해 간단한 테이블 뷰가 포함된 모달 뷰 컨트롤러로 통화를 대체했습니다.
이를 달성하는 방법은 여러 가지가 있습니다.여기 제가 최근 프로젝트에서 구현한 한 가지 방법이 있습니다.옵션 목록에서 모든 사용자가 선택할 수 있는 5~6개의 다른 화면에서 재사용할 수 있어 좋습니다.
- 클래스인 "UITableViewController"를 .
SimpleTableViewController
. - 스토리보드(내비게이션 컨트롤러에 포함됨)에 UITableViewController를 만들고 해당 사용자 지정 클래스를 SimpleTableViewController로 설정합니다.
- SimpleTableViewController의 탐색 컨트롤러에 "SimpleTableVC"의 스토리보드 ID를 지정합니다.
- SimpleTableViewController.h에서 테이블의 데이터를 나타내는 NSArray 속성을 만듭니다.
- 에서도 SimpleTableViewController 합니다.h에서도 프로토콜 생성
SimpleTableViewControllerDelegate
한itemSelectedatRow:
.id<SimpleTableViewControllerDelegate>
이렇게 하면 선택 항목을 상위 컨트롤러로 다시 전달할 수 있습니다. - 에서 SimpleTableViewController를 호출하여 뷰 및 메서드를 합니다.m에서 테이블 뷰 데이터 소스 및 위임 메서드를 구현하고 다음을 호출합니다.
itemSelectedatRow:
tableView:didSelectRowAtIndexPath:
.
이 접근 방식은 상당히 재사용 가능하다는 추가적인 이점이 있습니다.한 다음 "ViewController"를 합니다.h에서 SimpleTableViewController 클래스를 가져오고 SimpleTableViewDelegate를 준수하고itemSelectedAtRow:
을 열려면 새 SimpleTableViewController를 한 후합니다.그런 다음, 모달을 열려면 새 SimpleTableViewController를 인스턴스화하고 테이블 데이터를 설정하고 위임한 후 표시합니다.
UINavigationController *navigationController = (UINavigationController *)[self.storyboard instantiateViewControllerWithIdentifier:@"SimpleTableVC"];
SimpleTableViewController *tableViewController = (SimpleTableViewController *)[[navigationController viewControllers] objectAtIndex:0];
tableViewController.tableData = self.statesArray;
tableViewController.navigationItem.title = @"States";
tableViewController.delegate = self;
[self presentViewController:navigationController animated:YES completion:nil];
간단한 예시를 만들어서 github에 올렸습니다.
또한 작업 시트 표시로 인해 CGContext 잘못된 컨텍스트 오류가 발생합니다.를 참조하십시오.
이 질문에 대한 Marcio의 훌륭한 해결책은 UIAction에 모든 종류의 하위 뷰를 추가하는 데 큰 도움이 되었습니다.시트.
(아직) 완전히 명확하지 않은 이유로, UIAction의 경계.시트는 표시된 후에만 설정할 수 있습니다. Sagar 및 Marcio의 솔루션은 setBounds를 사용하여 이 문제를 성공적으로 해결합니다.CGRectMake(...) 메시지가 표시된 후 작업 시트로 전송됩니다.
그러나 UIAction 설정시트가 표시된 후의 시트 경계는 동작 시 점프 전환을 생성합니다.시트가 표시되고 "팝업"되어 보기에 표시된 다음 마지막 40픽셀 이상에서만 스크롤됩니다.
하위 뷰를 추가한 후 UI PickerView 크기를 조정할 때 작업에 전송된 setBounds 메시지를 래핑하는 것이 좋습니다.애니메이션 블록 내부의 시트입니다.이렇게 하면 작업이 시작됩니다.시트가 더 매끄럽게 나타납니다.
UIActionSheet *actionSheet = [[[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
// add one or more subviews to the UIActionSheet
// this could be a UIPickerView, or UISegmentedControl buttons, or any other
// UIView. Here, let's just assume it's already set up and is called
// (UIView *)mySubView
[actionSheet addSubview:myView];
// show the actionSheet
[actionSheet showInView:[UIApplication mainWindow]];
// Size the actionSheet with smooth animation
[UIView beginAnimations:nil context:nil];
[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
[UIView commitAnimations];
DatePicker DoneClick 기능을 찾으려는 사람들을 위해...다음은 조치 시트를 해제하는 간단한 코드입니다.분명히 aac은 ivar(당신의 구현 .h 파일에 있는 아이바)여야 합니다.
- (void)DatePickerDoneClick:(id)sender{
[aac dismissWithClickedButtonIndex:0 animated:YES];
}
나는 정말 이해할 수 없습니다 왜.UIPickerView
안으로 들어가는 중입니다.UIActionSheet
이것은 지저분하고 엉터리 솔루션으로 보이며, 향후 iOS 릴리스에서 깨질 수 있습니다.(예전에 앱에서 이런 휴식을 취한 적이 있습니다.UIPickerView
첫 번째 탭에서 제시되지 않았고 재캡처되어야 했습니다. - 이상한 농담입니다.UIActionSheet
).
제가 한 것은 단순히 다음과 같은 것을 구현한 것입니다.UIPickerView
그런 다음 제 보기에 하위 보기로 추가하고 마치 액션 시트처럼 위로 이동하는 애니메이션을 만듭니다.
/// Add the PickerView as a private variable
@interface EMYourClassName ()
@property (nonatomic, strong) UIPickerView *picker;
@property (nonatomic, strong) UIButton *backgroundTapButton;
@end
///
/// This is your action which will present the picker view
///
- (IBAction)showPickerView:(id)sender {
// Uses the default UIPickerView frame.
self.picker = [[UIPickerView alloc] initWithFrame:CGRectZero];
// Place the Pickerview off the bottom of the screen, in the middle set the datasource delegate and indicator
_picker.center = CGPointMake([[UIScreen mainScreen] bounds].size.width / 2.0, [[UIScreen mainScreen] bounds].size.height + _picker.frame.size.height);
_picker.dataSource = self;
_picker.delegate = self;
_picker.showsSelectionIndicator = YES;
// Create the toolbar and place it at -44, so it rests "above" the pickerview.
// Borrowed from @Spark, thanks!
UIToolbar *pickerDateToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, -44, 320, 44)];
pickerDateToolbar.barStyle = UIBarStyleBlackTranslucent;
[pickerDateToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
// The action can whatever you want, but it should dimiss the picker.
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(backgroundTapped:)];
[barItems addObject:doneBtn];
[pickerDateToolbar setItems:barItems animated:YES];
[_picker addSubview:pickerDateToolbar];
// If you have a UITabBarController, you should add the picker as a subview of it
// so it appears to go over the tabbar, not under it. Otherwise you can add it to
// self.view
[self.tabBarController.view addSubview:_picker];
// Animate it moving up
[UIView animateWithDuration:.3 animations:^{
[_picker setCenter:CGPointMake(160, [[UIScreen mainScreen] bounds].size.height - 148)]; //148 seems to put it in place just right.
} completion:^(BOOL finished) {
// When done, place an invisible button on the view behind the picker, so if the
// user "taps to dismiss" the picker, it will go away. Good user experience!
self.backgroundTapButton = [UIButton buttonWithType:UIButtonTypeCustom];
_backgroundTapButton.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[_backgroundTapButton addTarget:self action:@selector(backgroundTapped:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_backgroundTapButton];
}];
}
// And lastly, the method to hide the picker. You should handle the picker changing
// in a method with UIControlEventValueChanged on the pickerview.
- (void)backgroundTapped:(id)sender {
[UIView animateWithDuration:.3 animations:^{
_picker.center = CGPointMake(160, [[UIScreen mainScreen] bounds].size.height + _picker.frame.size.height);
} completion:^(BOOL finished) {
[_picker removeFromSuperview];
self.picker = nil;
[self.backgroundTapButton removeFromSuperview];
self.backgroundTapButton = nil;
}];
}
마르시오의 멋진 해결책을 더하자면,dismissActionSheet:
다음과 같이 구현할 수 있습니다.
- 작업 추가개체를 .h 파일에 시트하고, 합성한 다음 .m 파일에서 참조합니다.
코드에 이 메서드를 추가합니다.
- (void)dismissActionSheet:(id)sender{ [_actionSheet dismissWithClickedButtonIndex:0 animated:YES]; [_myButton setTitle:@"new title"]; //set to selected text if wanted }
저는 이것이 그것을 하는 가장 좋은 방법이라고 생각합니다.
그것은 모든 사람들이 제안하는 것과 거의 비슷하지만, 블록을 사용하는데, 이것은 좋은 터치입니다!
iOS 8부터, 당신은 할 수 없습니다, 애플이 내부 구현을 변경했기 때문에 작동하지 않습니다.UIActionSheet
Apple 설명서를 참조하십시오.
하위 분류 노트
UIAction시트는 하위 분류되도록 설계되지 않았으며, 시트의 계층 구조에 뷰를 추가해서는 안 됩니다.UIAction에서 제공하는 것보다 더 많은 사용자 정의가 포함된 시트를 제시해야 하는 경우Sheet API, 직접 생성하여 presentViewController:animated:completion:를 사용하여 모듈식으로 표시할 수 있습니다.
저는 Wayfarer와 flexaddicted의 접근 방식이 마음에 들었지만 백그라운드 TapButton이 사용자 상호 작용에 응답하는 유일한 요소이기 때문에 (Ztral처럼) 작동하지 않는다는 것을 발견했습니다.이것은 제가 그의 세 개의 서브뷰를 모두 넣게 했습니다: _picker, _picker.도구 모음 및 배경화면에 애니메이션으로 표시된 보기(팝업) 안에 있는 단추를 누릅니다._picker의 Cancel 버튼도 필요했습니다.도구 모음.다음은 팝업 보기와 관련된 코드 요소입니다(사용자 자신의 선택기 데이터 원본 및 위임 방법을 제공해야 함).
#define DURATION 0.4
#define PICKERHEIGHT 162.0
#define TOOLBARHEIGHT 44.0
@interface ViewController ()
@property (nonatomic, strong) UIView *popup;
@property (nonatomic, strong) UIPickerView *picker;
@property (nonatomic, strong) UIToolbar *pickerToolbar;
@property (nonatomic, strong) UIButton *backgroundTapButton;
@end
-(void)viewDidLoad {
// These are ivars for convenience
rect = self.view.bounds;
topNavHeight = self.navigationController.navigationBar.frame.size.height;
bottomNavHeight = self.navigationController.toolbar.frame.size.height;
navHeights = topNavHeight + bottomNavHeight;
}
-(void)showPickerView:(id)sender {
[self createPicker];
[self createToolbar];
// create view container
_popup = [[UIView alloc] initWithFrame:CGRectMake(0.0, topNavHeight, rect.size.width, rect.size.height - navHeights)];
// Initially put the centre off the bottom of the screen
_popup.center = CGPointMake(rect.size.width / 2.0, rect.size.height + _popup.frame.size.height / 2.0);
[_popup addSubview:_picker];
[_popup insertSubview:_pickerToolbar aboveSubview:_picker];
// Animate it moving up
// This seems to work though I am not sure why I need to take off the topNavHeight
CGFloat vertCentre = (_popup.frame.size.height - topNavHeight) / 2.0;
[UIView animateWithDuration:DURATION animations:^{
// move it to a new point in the middle of the screen
[_popup setCenter:CGPointMake(rect.size.width / 2.0, vertCentre)];
} completion:^(BOOL finished) {
// When done, place an invisible 'button' on the view behind the picker,
// so if the user "taps to dismiss" the picker, it will go away
self.backgroundTapButton = [UIButton buttonWithType:UIButtonTypeCustom];
_backgroundTapButton.frame = CGRectMake(0, 0, _popup.frame.size.width, _popup.frame.size.height);
[_backgroundTapButton addTarget:self action:@selector(doneAction:) forControlEvents:UIControlEventTouchUpInside];
[_popup insertSubview:_backgroundTapButton belowSubview:_picker];
[self.view addSubview:_popup];
}];
}
-(void)createPicker {
// To use the default UIPickerView frame of 216px set frame to CGRectZero, but we want the 162px height one
CGFloat pickerStartY = rect.size.height - navHeights - PICKERHEIGHT;
self.picker = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, pickerStartY, rect.size.width, PICKERHEIGHT)];
_picker.dataSource = self;
_picker.delegate = self;
_picker.showsSelectionIndicator = YES;
// Otherwise you can see the view underneath the picker
_picker.backgroundColor = [UIColor whiteColor];
_picker.alpha = 1.0f;
}
-(void)createToolbar {
CGFloat toolbarStartY = rect.size.height - navHeights - PICKERHEIGHT - TOOLBARHEIGHT;
_pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, toolbarStartY, rect.size.width, TOOLBARHEIGHT)];
[_pickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelAction:)];
[barItems addObject:cancelButton];
// Flexible space to make the done button go on the right
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
// The done button
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneAction:)];
[barItems addObject:doneButton];
[_pickerToolbar setItems:barItems animated:YES];
}
// The method to process the picker, if we have hit done button
- (void)doneAction:(id)sender {
[UIView animateWithDuration:DURATION animations:^{
_popup.center = CGPointMake(rect.size.width / 2.0, rect.size.height + _popup.frame.size.height / 2.0);
} completion:^(BOOL finished) { [self destroyPopup]; }];
// Do something to process the returned value from your picker
}
// The method to process the picker, if we have hit cancel button
- (void)cancelAction:(id)sender {
[UIView animateWithDuration:DURATION animations:^{
_popup.center = CGPointMake(rect.size.width / 2.0, rect.size.height + _popup.frame.size.height / 2.0);
} completion:^(BOOL finished) { [self destroyPopup]; }];
}
-(void)destroyPopup {
[_picker removeFromSuperview];
self.picker = nil;
[_pickerToolbar removeFromSuperview];
self.pickerToolbar = nil;
[self.backgroundTapButton removeFromSuperview];
self.backgroundTapButton = nil;
[_popup removeFromSuperview];
self.popup = nil;
}
언급URL : https://stackoverflow.com/questions/1262574/add-uipickerview-a-button-in-action-sheet-how
'programing' 카테고리의 다른 글
iOS에서 뷰 계층을 검사하려면 어떻게 해야 합니까? (0) | 2023.06.12 |
---|---|
Oracle의 SYS_GUID() UUID RFC 4122가 호환됩니까? (0) | 2023.06.12 |
여러 data.frame을 여러 Excel 워크시트로 쉽게 내보낼 수 있는 방법 (0) | 2023.06.12 |
createReducer 함수를 사용할 때 생산을 위해 angular+ngrx 8을 빌드하는 동안 오류가 발생했습니다. (0) | 2023.06.12 |
지리적 근접 공식(스토어 로케이터)으로 인해 결과 누락 (0) | 2023.06.12 |