Это лучший сценарий для использования CoordinatorLayout в вашем приложении. КоординаторLayout представляет собой супермощный FrameLayout, который имеет множество отличных анимационных трюков на рукавах.
Библиотека Design представляет интерфейс CoordinatorLayout, который обеспечивает дополнительный уровень контроля над событиями касания между дочерними просмотров, что многие из компонентов библиотеки Design используют.
Вы можете начать с этого и этого учебника .
Эта ссылка объясняет мой вопрос довольно подробно:
Вот очень простой пример. Это показывает красный квадрат. Если вы перетащите изображение на красный квадрат, оно добавит его к телу. Я подтвердил, что он работает в IE11, Chrome 38 и Firefox 32. Более подробное объяснение см. В статье Html5Rocks .
var dropZone = document.getElementById('dropZone');
// Optional. Show the copy icon when dragging over. Seems to only work for chrome.
dropZone.addEventListener('dragover', function(e) {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
});
// Get file data on drop
dropZone.addEventListener('drop', function(e) {
e.stopPropagation();
e.preventDefault();
var files = e.dataTransfer.files; // Array of all files
for (var i=0, file; file=files[i]; i++) {
if (file.type.match(/image.*/)) {
var reader = new FileReader();
reader.onload = function(e2) {
// finished reading file data.
var img = document.createElement('img');
img.src= e2.target.result;
document.body.appendChild(img);
}
reader.readAsDataURL(file); // start reading the file data.
}
}
});
<div id="dropZone" style="width: 100px; height: 100px; background-color: red"></div>
Посмотрите на событие. Вы можете просто иметь внутреннюю часть div, которая будет скрыта до тех пор, пока событие ondragover не запустит функцию, которая покажет div с внутри него, что позволяет пользователю перетаскивать файл. Наличие декларации onchange позволяет автоматически вызывать функцию (например, выгрузку) при добавлении файла к входным данным. Убедитесь, что ввод допускает несколько файлов, так как вы не можете контролировать, сколько они будут пытаться перетащить в браузер.
Принятый ответ предоставляет отличную ссылку на эту тему; однако, согласно правилам SO, следует избегать чистых ссылок, поскольку они могут исчезнуть в любое время. По этой причине я нашел время, чтобы обобщить содержание ссылки для будущих читателей.
Прежде чем внедрять метод загрузки файлов на свой веб-сайт, вы должны убедиться, что браузеры, которые вы выбираете для поддержки, будут в состоянии полностью поддерживать File API ]. Вы можете быстро проверить это с помощью фрагмента Javascript ниже:
// Check for the various File API support.
if (window.File && window.FileReader && window.FileList && window.Blob) {
// Great success! All the File APIs are supported.
} else {
alert('The File APIs are not fully supported in this browser.');
}
Вы можете изменить приведенный выше фрагмент, чтобы, конечно, удовлетворить ваши потребности.
Самый распространенный способ загрузки файла - использовать стандартный элемент <input type="file">
. JavaScript возвращает список выбранных объектов File
как FileList
.
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++) {
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
'</li>');
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
Внесение простых изменений в приведенный выше фрагмент кода позволяет нам предоставить поддержка перетаскивания.
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
var files = evt.dataTransfer.files; // FileList object.
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++) {
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
'</li>');
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}
// Setup the dnd listeners.
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
<div id="drop_zone">Drop files here</div>
<output id="list"></output>
Теперь вы получили ссылку на File
Вы можете создать экземпляр FileReader
для чтения его содержимого в память. Когда загрузка завершается, вызывается событие onload
, и его атрибут result
может использоваться для доступа к данным файла. Не стесняйтесь смотреть ссылки на FileReader
, чтобы охватить четыре доступных варианта для чтения файла.
В приведенном ниже примере отфильтровываются изображения по выбору пользователя, вызывается reader.readAsDataURL()
для файла и отображается миниатюра путем установки атрибута src
для URL-адреса данных.
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
.thumb {
height: 75px;
border: 1px solid #000;
margin: 10px 5px 0 0;
}
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
В некоторых случаях чтение всего файла в память не выполняется. не лучший вариант. Например, допустим, вы хотите написать загрузчик асинхронных файлов. Одним из возможных способов ускорить загрузку было бы чтение и отправка файла в отдельных блоках диапазона байтов. Серверный компонент будет тогда отвечать за восстановление содержимого файла в правильном порядке.
Следующий пример демонстрирует чтение фрагментов файла. Стоит отметить, что он использует onloadend
и проверяет evt.target.readyState
вместо использования события onload
.
function readBlob(opt_startByte, opt_stopByte) {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
document.getElementById('byte_content').textContent = evt.target.result;
document.getElementById('byte_range').textContent =
['Read bytes: ', start + 1, ' - ', stop + 1,
' of ', file.size, ' byte file'].join('');
}
};
var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
}
document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);
#byte_content {
margin: 5px 0;
max-height: 100px;
overflow-y: auto;
overflow-x: hidden;
}
#byte_range { margin-top: 5px; }
<input type="file" id="files" name="file" /> Read bytes:
<span class="readBytesButtons">
<button data-startbyte="0" data-endbyte="4">1-5</button>
<button data-startbyte="5" data-endbyte="14">6-15</button>
<button data-startbyte="6" data-endbyte="7">7-8</button>
<button>entire file</button>
</span>
<div id="byte_range"></div>
<div id="byte_content"></div>
Одна из приятных вещей, которые мы получаем за бесплатно при использовании асинхронной обработки событий есть возможность следить за ходом чтения файла; полезно для больших файлов, выявления ошибок и выяснения, когда чтение завершено.
События onloadstart
и onprogress
могут использоваться для отслеживания хода чтения.
Пример ниже демонстрирует отображение индикатора выполнения для контроля состояния чтения. Чтобы увидеть индикатор прогресса в действии, попробуйте большой файл или файл с удаленного диска.
var reader;
var progress = document.querySelector('.percent');
function abortRead() {
reader.abort();
}
function errorHandler(evt) {
switch(evt.target.error.code) {
case evt.target.error.NOT_FOUND_ERR:
alert('File Not Found!');
break;
case evt.target.error.NOT_READABLE_ERR:
alert('File is not readable');
break;
case evt.target.error.ABORT_ERR:
break; // noop
default:
alert('An error occurred reading this file.');
};
}
function updateProgress(evt) {
// evt is an ProgressEvent.
if (evt.lengthComputable) {
var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
// Increase the progress bar length.
if (percentLoaded < 100) {
progress.style.width = percentLoaded + '%';
progress.textContent = percentLoaded + '%';
}
}
}
function handleFileSelect(evt) {
// Reset progress indicator on new file selection.
progress.style.width = '0%';
progress.textContent = '0%';
reader = new FileReader();
reader.onerror = errorHandler;
reader.onprogress = updateProgress;
reader.onabort = function(e) {
alert('File read cancelled');
};
reader.onloadstart = function(e) {
document.getElementById('progress_bar').className = 'loading';
};
reader.onload = function(e) {
// Ensure that the progress bar displays 100% at the end.
progress.style.width = '100%';
progress.textContent = '100%';
setTimeout("document.getElementById('progress_bar').className='';", 2000);
}
// Read in the image file as a binary string.
reader.readAsBinaryString(evt.target.files[0]);
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
#progress_bar {
margin: 10px 0;
padding: 3px;
border: 1px solid #000;
font-size: 14px;
clear: both;
opacity: 0;
-moz-transition: opacity 1s linear;
-o-transition: opacity 1s linear;
-webkit-transition: opacity 1s linear;
}
#progress_bar.loading {
opacity: 1.0;
}
#progress_bar .percent {
background-color: #99ccff;
height: auto;
width: 0;
}
<input type="file" id="files" name="file" />
<button onclick="abortRead();">Cancel read</button>
<div id="progress_bar"><div class="percent">0%</div></div>