├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── libraries │ ├── android_gesture_detectors_3cdeab048d.xml │ ├── appcompat_v7_22_2_0.xml │ ├── support_annotations_22_2_0.xml │ └── support_v4_22_2_0.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml ├── vcs.xml └── workspace.xml ├── LICENSE ├── MultiTouchPlaceholderView.iml ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── lb │ │ └── com │ │ └── multi_touch_placeholder_view │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── lb │ │ └── multi_touch_placeholder_view │ │ ├── BitmapDisplayActivity.java │ │ ├── MainActivity.java │ │ ├── MultiTouchContainer.java │ │ ├── MultiTouchImageView.java │ │ └── SquareImageView.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ ├── background.png │ ├── ic_launcher.png │ └── moving_image.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable │ └── frame.xml │ ├── layout │ ├── activity_main.xml │ └── bitmap_display.xml │ ├── menu │ └── activity_main.xml │ └── values │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── demo.gif ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | /*/build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | MultiTouchPlaceholderView -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/libraries/android_gesture_detectors_3cdeab048d.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/appcompat_v7_22_2_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/libraries/support_annotations_22_2_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/support_v4_22_2_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 57 | 58 | 59 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 148 | 149 | 150 | 152 | 153 | 177 | 1109 | 1139 | 1428 | 1431 | 1432 | 1433 | 1444 | 1445 | 1446 | 1451 | 1452 | 1453 | 1454 | 1455 | 1456 | 1461 | 1462 | 1463 | 1464 | 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | 1474 | 1475 | 1476 | 1477 | 1478 | 1479 | 1480 | 1481 | 1482 | 1483 | 1484 | 1485 | 1486 | 1487 | 1488 | 1491 | 1492 | 1495 | 1496 | 1497 | 1498 | 1501 | 1502 | 1505 | 1506 | 1507 | 1508 | 1509 | 1510 | 1511 | 1512 | 1513 | 1514 | 1515 | 1516 | 1517 | 1518 | 1519 | 1520 | 1521 | 1522 | 1523 | 1524 | 1525 | 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | 1532 | 1533 | 1534 | 1535 | 1536 | 1563 | 1564 | 1565 | 1593 | 1594 | 1595 | 1608 | 1609 | 1610 | 1611 | 1625 | 1626 | 1627 | 1628 | 1629 | 1630 | 1631 | 1632 | 1633 | 1634 | 1635 | 1642 | 1643 | 1644 | 1645 | 1663 | 1670 | 1671 | 1672 | 1699 | 1700 | 1701 | 1702 | 1703 | 1711 | 1712 | 1714 | 1715 | 1716 | 1717 | 1718 | 1719 | 1720 | 1721 | 1722 | 1435014218329 1723 | 1726 | 1727 | 1728 | 1729 | 1730 | 1731 | 1732 | 1733 | 1734 | 1735 | 1736 | 1737 | 1738 | 1739 | 1740 | 1741 | 1742 | 1743 | 1744 | 1745 | 1746 | 1747 | 1748 | 1749 | 1750 | 1751 | 1752 | 1753 | 1754 | 1755 | 1756 | 1757 | 1758 | 1759 | 1760 | 1761 | 1762 | 1765 | 1768 | 1769 | 1770 | 1772 | 1773 | 1774 | 1775 | 1776 | file://$PROJECT_DIR$/app/src/main/java/com/lb/multi_touch_placeholder_view/MainActivity.java 1777 | 69 1778 | 1779 | 1780 | 1781 | 1783 | 1784 | 1785 | 1786 | 1787 | 1788 | 1789 | 1790 | 1791 | 1792 | 1793 | 1794 | 1795 | 1796 | 1797 | 1798 | 1799 | 1800 | 1801 | 1802 | 1803 | 1804 | 1805 | 1806 | 1807 | 1808 | 1809 | 1810 | 1811 | 1812 | 1813 | 1814 | 1815 | 1816 | 1817 | 1818 | 1819 | 1820 | 1821 | 1822 | 1823 | 1824 | 1825 | 1826 | 1827 | 1828 | 1829 | 1830 | 1831 | 1832 | 1833 | 1834 | 1835 | 1836 | 1837 | 1838 | 1839 | 1840 | 1841 | 1842 | 1843 | 1844 | 1845 | 1846 | 1847 | 1848 | 1849 | 1850 | 1851 | 1852 | 1853 | 1854 | 1855 | 1856 | 1857 | 1858 | 1859 | 1860 | 1861 | 1862 | 1863 | 1864 | 1865 | 1866 | 1867 | 1868 | 1869 | 1870 | 1871 | 1872 | 1873 | 1874 | 1875 | 1876 | 1877 | 1878 | 1879 | 1880 | 1881 | 1882 | 1883 | 1884 | 1885 | 1886 | 1887 | 1888 | 1889 | 1890 | 1891 | 1892 | 1893 | 1894 | 1895 | 1896 | 1897 | 1898 | 1899 | 1900 | 1901 | 1902 | 1903 | 1904 | 1905 | 1906 | 1907 | 1908 | 1909 | 1910 | 1911 | 1912 | 1913 | 1914 | 1915 | 1916 | 1917 | 1918 | 1919 | 1920 | 1921 | 1922 | 1923 | 1924 | 1925 | 1926 | 1927 | 1928 | 1929 | 1930 | 1931 | 1932 | 1933 | 1934 | 1935 | 1936 | 1937 | 1938 | 1939 | 1940 | 1941 | 1942 | 1943 | 1944 | 1945 | 1946 | 1947 | 1948 | 1949 | 1950 | 1951 | 1952 | 1953 | 1954 | 1955 | 1956 | 1957 | 1958 | 1959 | 1960 | 1961 | 1962 | 1963 | 1964 | 1965 | 1966 | 1967 | 1968 | 1969 | 1970 | 1971 | 1972 | 1973 | 1974 | 1975 | 1976 | 1977 | 1978 | 1979 | 1980 | 1981 | 1982 | 1983 | 1984 | 1985 | 1986 | 1987 | 1988 | 1989 | 1990 | 1991 | 1992 | 1993 | 1994 | 1995 | 1996 | 1997 | 1998 | 1999 | 2000 | 2001 | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 | 2027 | 2028 | 2029 | 2030 | 2031 | 2032 | 2033 | 2034 | 2035 | 2036 | 2037 | 2038 | 2039 | 2040 | 2041 | 2042 | 2043 | 2044 | 2045 | 2046 | 2047 | 2048 | 2049 | 2050 | 2051 | 2052 | 2053 | 2054 | 2055 | 2056 | 2057 | 2058 | 2059 | 2060 | 2061 | 2062 | 2063 | 2064 | 2065 | 2066 | 2067 | 2068 | 2069 | 2070 | 2071 | 2072 | 2073 | 2074 | 2075 | 2076 | 2077 | 2078 | 2079 | 2080 | 2081 | 2082 | 2083 | 2084 | 2085 | 2086 | 2087 | 2088 | 2089 | 2090 | 2091 | 2092 | 2093 | 2094 | 2095 | 2096 | 2097 | 2098 | 2099 | 2100 | 2101 | 2102 | 2103 | 2104 | 2105 | 2106 | 2107 | 2108 | 2109 | 2110 | 2111 | 2112 | 2113 | 2114 | 2115 | 2116 | 2117 | 2118 | 2119 | 2120 | 2121 | 2122 | 2123 | 2124 | 2125 | 2126 | 2127 | 2128 | 2129 | 2130 | 2131 | 2132 | 2133 | 2134 | 2135 | 2136 | 2137 | 2138 | 2139 | 2140 | 2141 | 2142 | 2143 | 2144 | 2145 | 2146 | 2147 | 2148 | 2149 | 2150 | 2151 | 2152 | 2153 | 2154 | 2155 | 2156 | 2157 | 2158 | 2159 | 2160 | 2161 | 2162 | 2163 | 2164 | 2165 | 2166 | 2167 | 2168 | 2169 | 2170 | 2171 | 2172 | 2173 | 2174 | 2175 | 2176 | 2177 | 2178 | 2179 | 2180 | 2181 | 2182 | 2183 | 2184 | 2185 | 2186 | 2187 | 2188 | 2189 | 2190 | 2191 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, AndroidDeveloperLB 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /MultiTouchPlaceholderView.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MultiTouchPlaceholderView 2 | Gesture-based image layer, to move it into placeholders (empty content within a bitmap) 3 | 4 | This POC shows how to move,rotate, resize and change alpha an inner bitmap within an ImageView using gestures, and when you wish, prepare an output bitmap containing the changes. 5 | 6 | Note: the POC uses a library called ["android-gesture-detectors"](https://github.com/Almeros/android-gesture-detectors) in order to handle the various gestures. 7 | 8 | **Advantages** 9 | 10 | - Allows resizing using either 2 fingers or a single one (tap+dragTouch). 11 | - Allows panning 12 | - Allows shoving (moving of 2 fingers up/down) 13 | - Allows rotating using 2 fingers 14 | - You can add any view you wish, and allow the container to draw it. 15 | 16 | **Sample demo animation** 17 | 18 | Here's an animation to show what it's capable of: 19 | 20 | ![enter image description here](https://raw.githubusercontent.com/AndroidDeveloperLB/MultiTouchPlaceholderView/master/demo.gif) 21 | 22 | **License** 23 | 24 | This project is licensed with the 2-clause BSD license, as [the library](https://github.com/Almeros/android-gesture-detectors) this POC uses is under this license. 25 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | defaultConfig { 7 | applicationId 'com.lb.multi_touch_placeholder_view' 8 | minSdkVersion 11 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | repositories { 14 | maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } 15 | maven { 16 | url "https://jitpack.io" 17 | } 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | productFlavors { 26 | } 27 | } 28 | 29 | dependencies { 30 | compile fileTree(include: ['*.jar'], dir: 'libs') 31 | compile 'com.android.support:appcompat-v7:22.2.0' 32 | 33 | compile 'com.github.AndroidDeveloperLB:android-gesture-detectors:3cdeab048d' 34 | } 35 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/lb/com/multi_touch_placeholder_view/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package lb.com.multi_touch_placeholder_view; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase 10 | { 11 | public ApplicationTest() 12 | { 13 | super(Application.class); 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/lb/multi_touch_placeholder_view/BitmapDisplayActivity.java: -------------------------------------------------------------------------------- 1 | package com.lb.multi_touch_placeholder_view; 2 | import android.graphics.Bitmap; 3 | import android.widget.ImageView; 4 | 5 | public class BitmapDisplayActivity extends android.app.Activity 6 | { 7 | public static Bitmap _bitmap; 8 | 9 | @Override 10 | protected void onCreate(final android.os.Bundle savedInstanceState) 11 | { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.bitmap_display); 14 | ImageView imageView=(ImageView)findViewById(R.id.imageView); 15 | imageView.setImageBitmap(_bitmap); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/lb/multi_touch_placeholder_view/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.lb.multi_touch_placeholder_view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Bitmap.Config; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.BitmapFactory.Options; 8 | import android.graphics.Rect; 9 | import android.os.Build.VERSION; 10 | import android.os.Build.VERSION_CODES; 11 | import android.os.Bundle; 12 | import android.support.v7.app.AppCompatActivity; 13 | import android.view.MotionEvent; 14 | import android.view.View; 15 | import android.view.View.OnClickListener; 16 | import android.view.View.OnTouchListener; 17 | import android.view.ViewTreeObserver.OnPreDrawListener; 18 | import android.widget.ImageView; 19 | import android.widget.RelativeLayout; 20 | import android.widget.Toast; 21 | 22 | public class MainActivity extends AppCompatActivity 23 | { 24 | 25 | private MultiTouchImageView mMultiTouchImageView; 26 | 27 | @SuppressWarnings("deprecation") 28 | @Override 29 | public void onCreate(Bundle savedInstanceState) 30 | { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_main); 33 | final MultiTouchContainer multiTouchContainer=(MultiTouchContainer)findViewById(R.id.container); 34 | mMultiTouchImageView=new MultiTouchImageView(this); 35 | final Bitmap movingBitmap=BitmapFactory.decodeResource(getResources(),R.drawable.moving_image); 36 | final Bitmap background=decodeMutableBitmapFromResourceId(this,R.drawable.background); 37 | final ImageView backgroundImageView=(ImageView)findViewById(android.R.id.background); 38 | final int bgBitmapWidth=background.getWidth(), bgBitmapHeight=background.getHeight(); 39 | 40 | // backgroundImageView.setAlpha(0.5f); 41 | backgroundImageView.setImageBitmap(background); 42 | multiTouchContainer.setOnTouchListener(new OnTouchListener() 43 | { 44 | @Override 45 | public boolean onTouch(final View v,final MotionEvent event) 46 | { 47 | return mMultiTouchImageView.onTouch(event); 48 | } 49 | }); 50 | runJustBeforeBeingDrawn(multiTouchContainer,new Runnable() 51 | { 52 | @Override 53 | public void run() 54 | { 55 | final int bgViewWidth=multiTouchContainer.getWidth(), bgViewHeight=multiTouchContainer.getHeight(); 56 | // handle the moving imageView 57 | mMultiTouchImageView.setMovingBitmap(movingBitmap); 58 | mMultiTouchImageView.setEnableGestures(true); 59 | mMultiTouchImageView.setOnClickListener(new OnClickListener() 60 | { 61 | @Override 62 | public void onClick(final View v) 63 | { 64 | Toast.makeText(MainActivity.this,"click",Toast.LENGTH_SHORT).show(); 65 | } 66 | }); 67 | mMultiTouchImageView.setClickable(false); 68 | //this is where you wish to put the boundaries of the moving imageView, in relation to the bitmap: 69 | final Rect boundingBox=new Rect(bgBitmapWidth/4,bgBitmapHeight/4,bgBitmapWidth*3/4,bgBitmapHeight*3/4); 70 | RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(bgViewWidth*boundingBox.width()/bgBitmapWidth,bgViewHeight*boundingBox.height()/bgBitmapHeight); 71 | layoutParams.leftMargin=bgViewWidth*boundingBox.left/bgBitmapWidth; 72 | layoutParams.topMargin=bgViewHeight*boundingBox.top/bgBitmapHeight; 73 | multiTouchContainer.addView(mMultiTouchImageView,0,layoutParams); 74 | findViewById(R.id.viewOutputBitmapButton).setOnClickListener(new View.OnClickListener() 75 | { 76 | @Override 77 | public void onClick(final View v) 78 | { 79 | Bitmap bmp2=Bitmap.createBitmap(bgBitmapWidth,bgBitmapHeight,Config.ARGB_8888); 80 | final Bitmap outputBitmap=multiTouchContainer.finishDrawing(bmp2); 81 | BitmapDisplayActivity._bitmap=outputBitmap; 82 | startActivity(new android.content.Intent(MainActivity.this,BitmapDisplayActivity.class)); 83 | finish(); 84 | } 85 | }); 86 | } 87 | }); 88 | 89 | } 90 | 91 | public static Bitmap decodeMutableBitmapFromResourceId(final Context context,final int bitmapResId) 92 | { 93 | final Options bitmapOptions=new Options(); 94 | if(VERSION.SDK_INT>=VERSION_CODES.HONEYCOMB) 95 | bitmapOptions.inMutable=true; 96 | Bitmap bitmap=BitmapFactory.decodeResource(context.getResources(),bitmapResId,bitmapOptions); 97 | return bitmap; 98 | } 99 | 100 | @Override 101 | public boolean onCreateOptionsMenu(final android.view.Menu menu) 102 | { 103 | getMenuInflater().inflate(R.menu.activity_main,menu); 104 | return super.onCreateOptionsMenu(menu); 105 | } 106 | 107 | @SuppressWarnings("deprecation") 108 | @Override 109 | public boolean onOptionsItemSelected(final android.view.MenuItem item) 110 | { 111 | String url=null; 112 | switch(item.getItemId()) 113 | { 114 | case R.id.menuItem_all_my_apps: 115 | url="https://play.google.com/store/apps/developer?id=AndroidDeveloperLB"; 116 | break; 117 | case R.id.menuItem_all_my_repositories: 118 | url="https://github.com/AndroidDeveloperLB"; 119 | break; 120 | case R.id.menuItem_current_repository_website: 121 | url="https://github.com/AndroidDeveloperLB/MultiTouchPlaceholderView"; 122 | break; 123 | } 124 | if(url==null) 125 | return true; 126 | final android.content.Intent intent=new android.content.Intent(android.content.Intent.ACTION_VIEW,android.net.Uri.parse(url)); 127 | intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NO_HISTORY|android.content.Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 128 | intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK|android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK); 129 | startActivity(intent); 130 | return true; 131 | } 132 | 133 | /** 134 | * This method helps to retrieve the ui component size after it was create during the onCreate method 135 | * 136 | * @param view - the view to get it's size 137 | * @param runnable 138 | */ 139 | public static void runJustBeforeBeingDrawn(final View view,final Runnable runnable) 140 | { 141 | final OnPreDrawListener preDrawListener=new OnPreDrawListener() 142 | { 143 | @Override 144 | public boolean onPreDraw() 145 | { 146 | view.getViewTreeObserver().removeOnPreDrawListener(this); 147 | runnable.run(); 148 | return true; 149 | } 150 | }; 151 | view.getViewTreeObserver().addOnPreDrawListener(preDrawListener); 152 | } 153 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lb/multi_touch_placeholder_view/MultiTouchContainer.java: -------------------------------------------------------------------------------- 1 | package com.lb.multi_touch_placeholder_view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.util.TypedValue; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.EditText; 11 | import android.widget.RelativeLayout; 12 | 13 | public class MultiTouchContainer extends RelativeLayout 14 | { 15 | public MultiTouchContainer(final Context context) 16 | { 17 | super(context); 18 | } 19 | 20 | public MultiTouchContainer(final Context context,final android.util.AttributeSet attrs) 21 | { 22 | super(context,attrs); 23 | } 24 | 25 | public MultiTouchContainer(final Context context,final android.util.AttributeSet attrs,final int defStyleAttr) 26 | { 27 | super(context,attrs,defStyleAttr); 28 | } 29 | 30 | @android.annotation.TargetApi(android.os.Build.VERSION_CODES.LOLLIPOP) 31 | public MultiTouchContainer(final Context context,final android.util.AttributeSet attrs,final int defStyleAttr,final int defStyleRes) 32 | { 33 | super(context,attrs,defStyleAttr,defStyleRes); 34 | } 35 | 36 | @Override 37 | protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec) 38 | { 39 | super.onMeasure(widthMeasureSpec,heightMeasureSpec); 40 | int width=getMeasuredWidth(), height=getMeasuredHeight(); 41 | int size=Math.min(width,height); 42 | setMeasuredDimension(size,size); 43 | } 44 | 45 | protected void prepareDrawingOfChildToBitmap(View view,int bitmapWidth,int bitmapHeight,int layoutWidth,int layoutHeight) 46 | { 47 | view.setAlpha(1); 48 | if(view instanceof EditText) 49 | { 50 | //make the EditText look like a normal TextView 51 | EditText editText=(EditText)view; 52 | editText.setTextColor(editText.getCurrentTextColor()); 53 | editText.setCursorVisible(false); 54 | editText.setTextSize(TypedValue.COMPLEX_UNIT_PX,bitmapHeight*editText.getTextSize()/layoutHeight); 55 | editText.setBackgroundColor(Color.TRANSPARENT); 56 | } 57 | if(view instanceof MultiTouchImageView) 58 | { 59 | MultiTouchImageView multiTouchImageView=(MultiTouchImageView)view; 60 | multiTouchImageView.setTranslate(bitmapWidth*multiTouchImageView.getTranslateX()/layoutWidth,bitmapHeight*multiTouchImageView.getTranslateY()/layoutHeight); 61 | multiTouchImageView.setScaleFactor(bitmapWidth*multiTouchImageView.getScaleFactorX()/layoutWidth,bitmapHeight*multiTouchImageView.getScaleFactorY()/layoutHeight); 62 | } 63 | final LayoutParams layoutParams=(LayoutParams)view.getLayoutParams(); 64 | layoutParams.leftMargin=bitmapWidth*layoutParams.leftMargin/layoutWidth; 65 | layoutParams.topMargin=bitmapHeight*layoutParams.topMargin/layoutHeight; 66 | layoutParams.rightMargin=bitmapWidth*layoutParams.rightMargin/layoutWidth; 67 | layoutParams.bottomMargin=bitmapHeight*layoutParams.bottomMargin/layoutHeight; 68 | int currentWidth=view.getId()==android.R.id.background?view.getWidth():layoutParams.width; 69 | layoutParams.width=currentWidth<=0?currentWidth:bitmapWidth*currentWidth/layoutWidth; 70 | int currentHeight=view.getId()==android.R.id.background?view.getHeight():layoutParams.height; 71 | layoutParams.height=currentHeight<=0?currentHeight:bitmapHeight*currentHeight/layoutHeight; 72 | view.setLayoutParams(layoutParams); 73 | } 74 | 75 | public Bitmap finishDrawing(final Bitmap bitmap) 76 | { 77 | Canvas canvas=new Canvas(bitmap); 78 | int childCount=getChildCount(); 79 | final int layoutWidth=getWidth(), layoutHeight=getHeight(); 80 | final int bitmapWidth=bitmap.getWidth(), bitmapHeight=bitmap.getHeight(); 81 | ViewGroup parent=(ViewGroup)getParent(); 82 | parent.removeView(this); 83 | for(int i=0;i 2 | 5 | 10 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | 21 |