Wednesday, November 22, 2017

Điều chỉnh giao diện ứng dụng cho iphone X

Iphone X mới ra có dải đen trên đầu màn hình.

Nếu cứ để bình thường thì phần trên ứng dụng sẽ bị che mất, có thể ảnh hưởng đến tương tác của người dùng. Ta sẽ lùi phần đầu xuống một khoảng để tránh khoảng đen đi. Để làm điều này ta cần biết chiều cao dải đen là bao nhiêu. Đây là thông số kỹ thuật của nó.

Vậy dải đen có chiều cao là 30pt, ta cũng biết kích thước màn hình của iphone X là 375x812 nên ta có thể đặt một biến tên là xle và dùng lệnh if như sau.
let c = UIScreen.mainScreen().bounds.size.height
Hoặc
let c = view.frame.size.height
        if c==812{
            xle = 30
        }
Sau đó khi set vị trí y của view như label chẳng hạn, ta dùng.
label = UILabel(frame: CGRect(x: 0, y: 15+xle, width: 320, height: 40))
Khi đó lúc chạy trên iphone X thì label sẽ tự dịch xuống một khoảng 30pt.
Vì thiết bị có chiều cao lớn hơn 800 ngoài iphone X chỉ còn các ipad màn hình lớn nên ta cũng có thể đặt trong lệnh if là c>800, lúc đó khoảng 30pt không là gì so với màn hình lớn nên không ảnh hưởng tới giao diện tổng thể.

Dùng Popover để hiển thị màn hình mới

Đôi khi ta muốn màn hình mới bật ra có dạng nổi giống như một Alert, chỉ cần thêm kiểu chuyển màn hình cho ViewController mới là Popover như sau.
let vc = second()
       
        vc.modalPresentationStyle = .Popover
        var popover = vc.popoverPresentationController   
        if let popover = vc.popoverPresentationController {      
            popover.sourceView = self.view           
            popover.sourceRect = CGRectMake(self.view.center.x,self.view.center.y+180,0,0)           
            vc.preferredContentSize = CGSizeMake(300,360)           
            popover.delegate = self
        }
       
        self.presentViewController(vc, animated: true, completion: nil)

Khi đó màn hình bật ra sẽ nổi ở giữa màn hình hiện tại, rộng 300, cao 360.


Ta sẽ phải điều chỉnh vị trí các view cho phù hợp với chiều rộng mới.

Lấy text từ trang web

Để đọc mạng lấy text từ trang web không phải thuần txt, ta dùng class sau.
class RequestTask extends AsyncTask<String, String, String>{
     @Override   
     protected String doInBackground(String... url) {
         
     HttpClient client = new DefaultHttpClient();
     HttpGet httpget = new HttpGet(url[0]);

     try {
     HttpResponse getResponse = client.execute(httpget);
     final int statusCode = getResponse.getStatusLine().getStatusCode();

     if(statusCode != HttpStatus.SC_OK) {
     Log.w("MyApp", "Download Error: " + statusCode + "| for URL: " + url);
                      return null;
                  }
     String line = "";
     StringBuilder total = new StringBuilder();
     HttpEntity getResponseEntity = getResponse.getEntity();
     BufferedReader reader = new BufferedReader(new InputStreamReader(getResponseEntity.getContent())); 

     while((line = reader.readLine()) != null) {
            total.append(line);
           }
  line = total.toString();
           return line;
          } catch (Exception e) {
             Log.w("MyApp", "Download Exception : " + e.toString());
          }
          return null;
     }
     @Override
     protected void onPostExecute(String result) {
             
     t.setText(result);
     }
     }
Gọi class bên dưới dòng setContentView, cho vào trong một progressBar để chờ.
mProgressDialog = new ProgressDialog(this);
           mProgressDialog.setMessage("Loading, please wait...");
            mProgressDialog.show();
        new Thread(new Runnable(){
            public void run(){
           
               new RequestTask().execute("http://llkqe.blogspot.com/2016/06/blog-post.html");
                if(mProgressDialog.isShowing())
                {
                   mProgressDialog.dismiss();
                }
            }
        }).start();
    }

Lúc này văn bản đọc ra trông như sau.

Để lấy được chuỗi cần dùng, ta xử lý chặt chuỗi và lấy String sau một String đặc biệt ta thêm vào trước chuỗi, ở đây là chữ “Đây”.
Khai báo mảng để add String cần lấy vào.
ArrayList<String> docmang = new ArrayList<String>();
Sau đó trong hàm @Override
          protected void onPostExecute(String result) {
Thay các dòng sau vào.
String l=result.toString();
             
String a[] = l.split(" ");
for (int i = 0; i < a.length; i++) { 
if(a[i].equals("Đây")){
docmang.add(a[i+7]);                   
  }
}
String r="";
for (int i = 0; i < docmang.size(); i++) {
r=r+docmang.get(i)+"\n";
}
t.setText(r+"");
Kết quả chạy ra sẽ như sau.

Để tránh bị crash khi không có mạng, cần kiểm tra kết nối mạng, để nếu không có mạng thì hiện Toast để người dùng biết.
Khi mới học lập trình, tôi thấy đọc ra toàn ký tự như giun dế nên nghĩ mình làm sai ở đâu đó nhưng không phải, cần xử lý thêm mới được.
Trong các sách dạy lập trình người ta dùng trang web thuần txt để làm ví dụ nên nếu không biết bạn chạy trang khác sẽ không ra giống như sách. Thực tế là phải xử lý thêm như trên, sách người ta không dạy cái ăn ngay được!
Cách này dùng để khi ta muốn làm ứng dụng cập nhật kết quả bóng đá thì post kết quả lên blog nào đó, mỗi khi người dùng mở app, ứng dụng sẽ tự vào đọc lấy kết quả ta đã post rồi xử lý cho vào chương trình.

Monday, November 13, 2017

Lưu dữ liệu với SharedPreferences

Để lưu dữ liệu trong Android ngoài cách ghi thành file txt ta cũng có thể dùng SharedPreferences.
int mode = Activity.MODE_PRIVATE;
final String MYPREFS = "mySave";
SharedPreferences save = getSharedPreferences(MYPREFS, mode);
SharedPreferences.Editor editor = save.edit();
editor.putBoolean("isTrue", true);
editor.putFloat("lastFloat", 1f);
editor.putInt("number", 2);
editor.putString("text", "Chu ghi vao");
editor.commit();

Khi lấy dữ liệu đã ghi thì dùng
final String MYPREFS = "mySave";
int mode = Activity.MODE_PRIVATE;
SharedPreferences myShare = getSharedPreferences(MYPREFS,mode);
           
boolean isTrue = myShare.getBoolean("isTrue", false);
float lastFloat = myShare.getFloat("lastFloat", 0f);
int number = myShare.getInt("number", 1);

String luu = myShare.getString("text","");
Hoặc ta có thể làm ngắn gọn hơn như sau.

final SharedPreferences.Editor edit = prefs.edit();
 edit.putInt("vi", vimoix);
 
edit.commit();  
Khi lấy thì dùng.

SharedPreferences prefs;
prefs=PreferenceManager.getDefaultSharedPreferences(this);
int so = prefs.getInt("vi", 0);
 

Để bàn phím không che TextField

Khi thiết kế giao diện, nếu TextField của bạn ở vị trí quá thấp thì khi người dùng ấn vào bàn phím hiện ra sẽ che mất TextField.
Để làm cho TextField tự cuộn lên được ta để giao diện trong một ScrollView Sc, sau dó thêm các hàm sau vào trên ngoặc đóng cuối cùng.
func keyboardShow(n:NSNotification) {
       
        let d = n.userInfo!
        var r = (d[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
        r = self.sc.convertRect(r, fromView:nil)
        self.sc.contentInset.bottom = r.size.height+50
        self.sc.scrollIndicatorInsets.bottom = r.size.height
    }
   
    func keyboardHide(sender: NSNotification!)
    {
        sc.setContentOffset(CGPointMake(0, 0), animated: false)
    }
Sau đó bên dưới dòng super.viewDidLoad() thêm các dòng sau.
NSNotificationCenter.defaultCenter().addObserver(
            self, selector: #selector(keyboardShow),
            name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(
            self, selector: #selector(ViewController.keyboardHide(_:)),
            name: UIKeyboardWillHideNotification, object: nil)

Bây giờ khi bạn chạm vào TextField nó sẽ tự cuộn lên không bị che nữa.