Bài viết‎ > ‎

Android: Hiệu ứng lật trang không dùng openGL

        Chào các bạn, hwa m đã gt cho các bạn cách chia text thành trang. Theo như đó, bạn có thể làm cho m 1 app đọc sách hoàn chỉnh. Nhg việc đọc như vậy chưa đc hấp dẫn cho lắm. Hni, m sẽ gt cho các bạn cách thêm hiệu ứng lật trang vào app.
       
         Kết quả của bài hni là:

       
        Hwa, m sử dụng ImageView để hiển thị ảnh, hni m sẽ dùng 1 custom view. Việc hiển thị sẽ do method onDraw() đảm nhận. Để đơn jản, m sẽ kok đưa text vào nữa mà sẽ dùng 2 ảnh để thay thế (việc đưa text vào làm như bài hwa). Hiệu ứng chuyển động sẽ do handler đảm nhận.

        Những quan sát ban đầu về việc lật trang sách:


        Khi bạn lật 1 trang sách lên, nếu nhìn từ trên xuống, chúng ta sẽ thấy tương tự như hình H1. Như vậy, nếu muốn vẽ đc hiệu ứng này, ta cần vẽ 3 layer như hình H2: trang ở trên (tr1) sẽ vẽ đầu tiên, sau đó sẽ vẽ 1fần trang 2 ở góc màn hình, cuối cùng là sẽ vẽ fần lật lên.

        Để thực hiện điều này, trong method onDraw() chúng ta dùng 2 method Canvas.clipPath(Path p) và Canvas.drawPath(Path p):
        + clipPath(Path p): cho fép bạn định nghĩa lại vùng vẽ, sau đó khi bạn vẽ bất kỳ hình nào thì chỉ có vùng path này đc hiển thị (Path đc khai báo bằng tọa độ màn hình).
        + drawPath(Path p): method này dùng để vẽ phần lật trang,

        
        Như vậy, muốn vẽ đc bạn cần xác định các Path hay chính là xác định các điểm (tọa độ x, y) tạo nên path. Sau đó, sẽ tao path bằng các method Path.moveTo(), Path.lineTo()... <xem thêm về Path trên trang của android>. Ở đây, chúng ta fải tìm 2 path: path fần lật và path fần hở ra.

        Xác định các điểm đó ntn?

        Khi lật sách lên, các bạn nhìn thấy fần lật có những đường cong, fần lật lên do hiệu ứng 3D sẽ luôn nhỏ hơn fần hiện ra. Để đơn jản, bạn hãy gập fần lật đó xuống(dĩ nhiên khi lật sách kok ai làm vậy cả :D), bi h bạn đã thấy 2 fần bằng nhau (fần lật và fần hở :D).
        
        Khi lật, bạn sẽ thấy đường chéo jao jữa 2 fần chạy từ trái qua fải như cái cần gạt nước của xe otô vậy. Chúng ta sẽ fải chọn lấy 1 gốc của "cần gạt" để tính toán dễ hơn. Dễ nhất là chọn ở các giá trị đã biết và m đã chọn (0, 2 x chiều dài) làm gốc (đây gần như là dk lý tưởng :D).

        Khi đường chéo này chạy, sẽ cắt trang tại 2 điểm, đây cũng chính là 2 điểm của path cần tìm. Để ý rằng, khi lật, trang trên sẽ đi hết fần màn hình, nên m sẽ chọn 1 điểm làm chỉ mục cho bắt đầu và kết thúc lật. Ở đây sẽ là giao của đường chéo với viền dưới của trang (điểm A). khi xA=width -> chưa lật, xA=0->lật xong.

        Hình bên dưới là các fép tính để tìm ra các điểm cần tìm:


           *Chú ý: ban đầu các path đều là hình tam giác, sau đó chuyển thành hình tứ giác. Do đó, để cùng dùng 1 method cho việc tạo path, path tam jác cũng đc tạo từ 4 điêm, vd: path fần hở ra là A-B-C-D, khi còn là tam jác, xD=xC nên ta vẫn có hình tam jác.

            Áp dụng cách tính trên, bạn có thể tạo hiệu ứng lật trang đơn jản. Nhưg vì dùng nhiều điểm cố dịnh nên bạn kok thể "play" với trang sách như video trên đc. Muốn đạt đc đáp ứng như video, bạn cần tạo ra các path fụ thuộc vào vị trí điểm F.

            Cũng với các tính toán như hình trên, chỉ là tính ngc từ F:


        Mã nguồn ở bên dưới là thực hiện đáp ứng theo điểm A, muốn đáp ứng theo điểm F, bạn tìm đoạn sau trong method onDraw():

            if(flipping){

                  pointGenerate(xTouchValue, width, height);

            }else {

                  //pointGenerateII(xTouchValue, yTouchValue, width, height);

                  pointGenerate(xTouchValue, width, height);

            }

    bỏ comment ở pointGenerateII và xóa dòng pointGenerate ở dưới đi.

        

        Bài viết tới đây là kết thúc. Hy vọng sẽ giúp ích cho các bạn.

Download sourcode


Comments