달력

11

« 2024/11 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
2020. 10. 8. 13:20

Swift에서 WKWebView Scroll 문제 해결 개발/Swift2020. 10. 8. 13:20

반응형

최근 회사에서 운영 중인 iOS 어플의 웹뷰를 앱 스토어의 권고 사항에 따라 UIWebView에서 WKWebView로 변경하였다.

WKWebView로 바꾸어서 그런지 일부 최신 폰에서 (보고 받은 것은 iPhone X, iPhone XR)

fixed 처리된 footer가 있는 줄 모르는 듯이 Scroll시 맨 아래까지 가지 않고 일부 내용을 가리게 되어 사용에 불편이 생겼다.

처음엔 그저 WKWebview의 문제인줄 알고 scroll bounces를 false로 적용하려고 하거나 status bar 문제 인가싶어 그 부분도 알아봤지만

더 찾아보니 iPhone 11에서 부터 Safe Area Zone이란 것이 생겨서 문제가 생긴 듯하였다.

그래서 해결한 코드를 공유하도록 하겠다.

 

import UIKit
import WebKit

class ViewController: UIViewController  {
    @IBOutlet var webView: WKWebView!
    
    private func setupWebView() {
        webView = WKWebView(frame: self.view.bounds, configuration: WKWebViewConfiguration())
        view.addSubview(webView)
        
        if #available(iOS 11.0, *) {
            webView.scrollView.contentInsetAdjustmentBehavior = .never
        } else {
            // Fallback on earlier versions
            webView.translatesAutoresizingMaskIntoConstraints = false
            view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["v0":webView]))
            view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-20-[v0]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["v0":webView]))
        }
    }
    
    override func viewSafeAreaInsetsDidChange() {
        if #available(iOS 11.0, *) {
            webView.translatesAutoresizingMaskIntoConstraints = false
            view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["v0":webView]))
            view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(\(self.view.safeAreaInsets.top))-[v0]-(\(self.view.safeAreaInsets.bottom))-|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["v0":webView]))
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setupWebView()
    }
}

위 코드처럼 iOS 11 버전 이상인지 아닌지에 따라 제약 조건을 분기하면 해결된다.

Safe Area Zone이 iOS 11 버전 이상부터 생김에 따라

safeAreaInsets 기능도 같이 iOS 11 버전 이상에서만 지원해주기 때문에 분기 코드는 필수이다.

만약, 하단은 가득 채우고 싶다면 25줄에서 -(\(self.view.safeAreaInsets.bottom))-를 삭제하면 된다.

 

 

참고 출처 : https://wit.nts-corp.com/2019/10/24/5731

stackoverflow.com/questions/45421548/ios-wkwebview-status-bar-padding

반응형
:
Posted by 리샤씨
반응형

 

https://risha-lee.tistory.com/34

 

ionic에서 android 상에 scroll 보이게 하기

오늘 ionic으로 만든 android app에서 scroll이 보이지 않아 보이게 해 달라는 요청에 의해 scroll이 보이도록 작업하였다. 특이하게도 ionic serve 명령어를 통해 웹으로 띄운 화면에서는 잘 보였는데 ionic

risha-lee.tistory.com

↑위 글과 연결된 글입니다.

 

 

지난 글에서 언급했듯이 요청받은 내용은 그냥 스크롤이 보이는 것이 아닌,

스크롤을 이동할 땐 보이지만, 스크롤을 이동하지 않을 땐 숨겨져 있는 기능이었다.

 

그래서 좀 생각해보았는데 어차피 기본은 안 보이는 것이고,

css를 추가해야만 보이니 class를 이용하여 토글 하면 좋겠다고 생각하였다.

 

그래서 아래의 코드 형태로 결과를 내게 되었다.

 

1. scss를 작성한다.

.scroll_view .scroll-content{
  overflow-y: overlay;
}
.scroll_view .scroll-content::-webkit-scrollbar {
  -webkit-appearance: none;
}
.scroll_view .scroll-content::-webkit-scrollbar:vertical {
  width: 3px;
}
.scroll_view .scroll-content::-webkit-scrollbar:horizontal {
  height: 3px;
}
.scroll_view .scroll-content::-webkit-scrollbar-thumb {
  border-radius: 8px;
  background-color: rgba(0, 0, 0, .5);
}

 

2. html을 작성한다.

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content [ngClass]="scrolling ? 'scroll_view' : ''" 
			(ionScrollStart)="scrollStart()" 
			(ionScrollEnd)="scrollEnd()">
            
            <!-- 본문 내용 작성 -->
            
</ion-content> 

 

3. ts를 작성한다.

import { Component, NgZone } from '@angular/core';
import { Platform  } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  scrolling = false;

  constructor(public platform: Platform,
              public _zone: NgZone) {
  }

  scrollStart() {
    if (this.platform.is('android')) { 
      console.log("scrollStart");
      this._zone.run(() => {
        this.scrolling = true;
      });
    }
  }

  scrollEnd() {
    if (this.platform.is('android')) { 
      console.log("scrollEnd");
      this._zone.run(() => {
        this.scrolling = false;
      });
    }
  }
}

 

위의 코드를 적용하여 android에서 실행해보면 스크롤을 이동할 때만 스크롤이 보여지는 것을 볼 수 있다.

 

여기서 NgZone은 좀 생소할 수도 있는데

일전에 연동되는 변수를 이용하여 화면을 열심히 바꿔도 적용이 되지 않아 찾은 기능이다.

https://angular.io/guide/zone에서 다시 찾아보니

NgZone을 사용하면 HTML에서 업데이트하기 위해 구성 요소의 변경 사항을 자동으로 감지할 수 있다고 한다.

나는 보통 NgZone제대로 코드를 작성하였는데도 뭔가 화면 변화가 이루어지지 않을 때, 사용해보는 편이다.

 

반응형
:
Posted by 리샤씨
반응형

오늘 ionic으로 만든 android app에서 scroll이 보이지 않아 보이게 해 달라는 요청에 의해

scroll이 보이도록 작업하였다.

 

특이하게도 ionic serve 명령어를 통해 웹으로 띄운 화면에서는 잘 보였는데

ionic cordova bulid 명령어를 통해 android에 올리면 보이지 않았다.

 

찾아보니 이 문제를 해결하고 싶은 경우가 좀 있었다.

ionic의 오류인 듯싶었다.

 

내가 적용한 해결법은 그냥 간단히 아래의 코드를 scss에 추가하면 된다.

(하지만 ios에서는 아쉽게도 작동하지 않았다. 추후 ios에서도 방법을 알게 된다면 글을 따로 올리도록 하겠다)

::-webkit-scrollbar {
  -webkit-appearance: none;
}
::-webkit-scrollbar:vertical {
  width: 3px;
}
::-webkit-scrollbar:horizontal {
  height: 3px;
}
::-webkit-scrollbar-thumb {
  border-radius: 8px;
  background-color: rgba(0, 0, 0, .5);
}

 

 

하지만 요청받은 내용은 그냥 스크롤이 보이는 것이 아닌,

스크롤을 이동할 땐 보이지만, 스크롤을 이동하지 않을 땐 숨겨져 있는 기능이었으므로

다음 글에서 해당 기능 추가하는 법을 설명하도록 하겠다.

 

 

출처 : https://stackoverflow.com/questions/43143299/ionic-scrollbar-is-not-visible-in-android-phone

반응형
:
Posted by 리샤씨
반응형

웹 개발을 하다 보면 보통 처음엔 퍼블리싱을 받지만

어쩔 수 없이 추가 개발이 들어와 기존에 있던 ui를 확장하여 새로운 ui 작업을 하기도 한다.

ui 고칠 일이 많거나 새로운 아이콘이 필요하다거나 잘 모르겠으면

퍼블리셔 분에게 요청하겠지만 간단한 것은 빠르게 내 선에서 해결하는 편이다.

 

이것도 그런 일 중 하나로, 관리자 페이지 특정 목록에서 엑셀 일괄 등록 기능이 새로 추가되는 일이었다.

엑셀 파일로 데이터를 업로드하여 진짜 테이블에 넣기 전에 임시 테이블에 넣어 확인하는 ui가 있었는데

엑셀로 등록하다 보니 나중에 행의 개수가 많아져 header가 고정되는 편이 좋을 것 같아 그렇게 작업했다.

 

처음엔 그냥 y축만 움직여서 작업하면 되어서 css로 충분히 작업이 가능하였으나

x축이 필요한 테이블이 생기게 되어 jQuery를 이용하는 아래 결과물이 나오게 되었다.

<style>
#userTbl {
  	width: 600px;
	height: 200px;
  	overflow-y: auto;
}
  	
#userTblHead {
  	width: 600px;
  	overflow-x: hidden;
}
  	
#userTbl table {
  	border-top: 0px;
}
  	
#userTblHead table {
  	overflow: hidden;
  	border-top: 2px solid #aaa;
  	border-bottom: 1px solid #aaa;
}
  	
.tblWrap table {
  	width: 100%;
  	border-spacing: 0;
  	border-width: 1px 0;
  	border-collapse: collapse;
  	table-layout: fixed;
}

.tblWrap table thead th {
	background: #eee;
}

.tblWrap table td {
	text-align: center;
	border-bottom: 1px solid #aaa;
}

.tblWrap table td.left {
	text-align: left;
	padding-left: 10px;
}

.tblWrap table th:not(:last-child), table td:not(:last-child) {
    border-right: solid 1px #aaa;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript">
var sl = 0;
$(function(){
	$.fn.hasYScrollBar = function() {
	    return (this.prop("scrollHeight") == 0 && this.prop("clientHeight") == 0)
	            || (this.prop("scrollHeight") > this.prop("clientHeight"));
	};

	$.fn.hasXScrollBar = function() {
	    return (this.prop("scrollWidth") == 0 && this.prop("clientWidth") == 0)
	            || (this.prop("scrollWidth") > this.prop("clientWidth"));
	};
	
	$("#userTbl").scroll(function(event){
		// data 테이블 x축 스크롤을 움직일 때header 테이블 x축 스크롤을 똑같이 움직인다
		if (sl != $("#userTbl").scrollLeft()) {
			sl = $("#userTbl").scrollLeft();
			$("#userTblHead").scrollLeft(sl);
		}
	});
	
	if ($("#userTbl").hasYScrollBar()) {
		//y축 스크롤이 있으면 스크롤 넓이인 17px만큼 header 마지막 열 크기를 늘린다
		$("#userTblHead colgroup col:last-child").width($("#userTbl colgroup col:last-child").width() + 17);
	} else {
		$("#userTblHead colgroup col:last-child").width($("#userTbl colgroup col:last-child").width());
	}
});
</script> 
<div class="tblWrap">
	<div id="userTblHead">
		<table>
			<!-- col의 width를 %가 아닌 px 단위로 정확히 지정해야 두 테이블이 하나의 테이블 처럼 보인다 -->
			<colgroup>
				<col style="width:45px">
				<col style="width:100px">
				<col style="width:100px">
				<col style="width:100px">
				<col style="width:100px">
				<col style="width:150px">
				<col style="width:200px">
				<col style="width:130px">
				<col style="width:130px">
			</colgroup>
			<thead>
				<tr>
					<th>No</th>
					<th>이름</th>
					<th>부서</th>
					<th>직급</th>
					<th>아이디</th>
					<th>전화번호</th>
					<th>이메일</th>
					<th>생년월일</th>
					<th>입사일</th>
				</tr>
			</thead>
		</table>
	</div>
	<div id="userTbl">
		<table>
			<colgroup>
				<col style="width:45px">
				<col style="width:100px">
				<col style="width:100px">
				<col style="width:100px">
				<col style="width:100px">
				<col style="width:150px">
				<col style="width:200px">
				<col style="width:130px">
				<col style="width:130px">
			</colgroup>
			<tbody>
				
				<tr>
					<td>1</td>
					<td>홍길동</td>
					<td>영업</td>
					<td>사원</td>
					<td>hong</td>
					<td>010-1000-1000</td>
					<td class="left">hong@company.co.kr</td>
					<td>1994-09-15</td>
					<td>2017-05-08</td>
				</tr>
				<tr>
					<td>2</td>
					<td>홍길동</td>
					<td>영업</td>
					<td>사원</td>
					<td>hong</td>
					<td>010-1000-1000</td>
					<td class="left">hong@company.co.kr</td>
					<td>1994-09-15</td>
					<td>2017-05-08</td>
				</tr>
				<tr>
					<td>3</td>
					<td>홍길동</td>
					<td>영업</td>
					<td>사원</td>
					<td>hong</td>
					<td>010-1000-1000</td>
					<td class="left">hong@company.co.kr</td>
					<td>1994-09-15</td>
					<td>2017-05-08</td>
				</tr>
				<tr>
					<td>4</td>
					<td>홍길동</td>
					<td>영업</td>
					<td>사원</td>
					<td>hong</td>
					<td>010-1000-1000</td>
					<td class="left">hong@company.co.kr</td>
					<td>1994-09-15</td>
					<td>2017-05-08</td>
				</tr>
				<tr>
					<td>5</td>
					<td>홍길동</td>
					<td>영업</td>
					<td>사원</td>
					<td>hong</td>
					<td>010-1000-1000</td>
					<td class="left">hong@company.co.kr</td>
					<td>1994-09-15</td>
					<td>2017-05-08</td>
				</tr>
				<tr>
					<td>6</td>
					<td>홍길동</td>
					<td>영업</td>
					<td>사원</td>
					<td>hong</td>
					<td>010-1000-1000</td>
					<td class="left">hong@company.co.kr</td>
					<td>1994-09-15</td>
					<td>2017-05-08</td>
				</tr>
				<tr>
					<td>7</td>
					<td>홍길동</td>
					<td>영업</td>
					<td>사원</td>
					<td>hong</td>
					<td>010-1000-1000</td>
					<td class="left">hong@company.co.kr</td>
					<td>1994-09-15</td>
					<td>2017-05-08</td>
				</tr>
				<tr>
					<td>8</td>
					<td>홍길동</td>
					<td>영업</td>
					<td>사원</td>
					<td>hong</td>
					<td>010-1000-1000</td>
					<td class="left">hong@company.co.kr</td>
					<td>1994-09-15</td>
					<td>2017-05-08</td>
				</tr>
				<tr>
					<td>9</td>
					<td>홍길동</td>
					<td>영업</td>
					<td>사원</td>
					<td>hong</td>
					<td>010-1000-1000</td>
					<td class="left">hong@company.co.kr</td>
					<td>1994-09-15</td>
					<td>2017-05-08</td>
				</tr>
			</tbody>
		</table>
	</div>
</div>

 

- y축 있을 때

No 이름 부서 직급 아이디 전화번호 이메일 생년월일 입사일
1 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08
2 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08
3 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08
4 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08
5 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08
6 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08
7 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08
8 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08
9 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08

 

- y축 없을 때

No 이름 부서 직급 아이디 전화번호 이메일 생년월일 입사일
1 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08
2 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08
3 홍길동 영업 사원 hong 010-1000-1000 hong@company.co.kr 1994-09-15 2017-05-08

 

아시다시피 html table은 header가 기본적으로 고정되지 않지만 위와 같이 편법을 쓰면 가능하다.

table header를 고정시키는 편법으로는 여러 가지 방법이 있으나

위 방법처럼 접근성엔 좋지 않은 header 테이블과 data 테이블을 나눈 이유는

내가 적용하려는 웹이 관리자 페이지이므로 접근성이 크게 상관없고,

저 방법으로 하면 ie와 Chrome 둘 다 열을 나누는 선이 있어도 y축이 있든 없든 예쁘게 보이기 때문이다.

반응형
:
Posted by 리샤씨


반응형
반응형