Есть данный макет. Область на которой находятся Card'ы. При свайпе справа-налево должны отображться следующие 2 элемента. Я делаю это с помощью ViewPager, но проблема в том, что ViewPager размещает по одному элементу в видимую область. Как решить эту проблему?
Ответ
Не претендую на завершенное решение, но кажется должна сработать такая идея. Все карды кладутся в горизонтальный LinearLayout, который оборачивается в HorizontalScrollView ……
…
Это даст нам возможность скроллить карды по горизонтали. Теперь нужно изменить ширину кардов так, чтобы на экран помещалось два карда. Для этого можно, например, унаследоваться от Card и переопределить onMeasure public class MyCard extends Card {
// … @Override
protected void onMeasure(int widthMeasureSpec, final int heightMeasureSpec) { final View parentScrollView = ((View)(getParent().getParent())); if (parentScrollView != null) {
if (parentScrollView instanceof HorizontalScrollView) {
widthMeasureSpec = parentScrollView.getMeasuredWidth() / 2;
}
}
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
}
Останется по событию скролла вычислить ближайшую позицию скролла, в которой на экране будут отображаться два карда целиком и вручную доскроллить через HorizontalScrollView.fullScroll(…)
Здравствуйте! Вопрос касается связи между компонентами React,а именно: передача данных из одного компонента в другой. Пусть есть страница , у которой есть массив объектов items. Для каждого элемента items создается компонент Код Layout.jsx: class Layout extends Component {
renderItems() {
var items = [
{name: 'Ivan', _id: '1'},
{name: 'Petya', _id: '2'}
]; return items.map( (each) => {
return (
);
});
} render() {
return (
{this.renderItems}
);
}
}
Код Item.jsx: class Item extends Component {
render() {
return (
{this.props.each.name}
);
}
}
Пусть теперь я хочу реализовать по щелчку на каждый вывод в консоль его _id. Сделать это внутри самого не составляет никакого труда: Новый код Item.jsx: class Item extends Component {
printId() {
console.log(this.props.each._id);
} render() {
return (
{this.props.each.name}
);
}
}
Но как быть, если нужно реализовать кнопку "Показать _id" снаружи, то есть в ? Допустим, внутри каждого добавим checkbox. Если этот чекбокс отмечен галочкой как selected, то при нажатии кнопки 'Показать _id' в консоль выводятся _id всех отмеченных Itemов. Но как передать _id отмеченных Itemов в ? Заранее благодарен за ответы.
Ответ
Ответ нашелся сразу в документации, спасибо @AlexeyTen за наводку. Пришлось помучиться, однако решение готов и оно ниже. При вызове функции из компонента someFunction.bind(this) мы можем передавать любое количество аргументов: someFunction.bind(this, arg1, arg2, ...). В этом и заключается ответ. Для примера выше: добавим функцию printId в компонент и навесим на компонент вызов printId по событию onClick. В качестве аргумента в функцию будем передавать текущий _id элемента. Новый код Layout.jsx: class Layout extends Component {
printId(id)
console.log(id); renderItems() {
var items = [
{name: 'Ivan', _id: '1'},
{name: 'Petya', _id: '2'}
]; return items.map( (each) => {
const eachId = each._id;
return (
);
});
} render() {
return (
{this.renderItems}
);
}
}
Однако, код выше не будет работать. Причина в том, что это не настоящий DOM-элемент, соответственно и события OnClick у него быть не может. В строке onCLick является обычным props. Для того, чтобы этот код работал, как ожидается, нужно внутри компонента у настоящего DOM-элемента прописать передачу настоящему onClick нашу функцию из props class Item extends Component {
render() {
return (
На что влияет адрес хоста у создателя подпрограммы в MySQL? Например, при создании подпрограммы (хранимой процедуры, функции, триггера и т.д.) определяется создатель подпрограммы (DEFINER): CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1()
SQL SECURITY DEFINER
BEGIN
UPDATE t1 SET counter = counter + 1;
END;
На что тогда влияет адрес? Например, что бы изменилось, если бы вместо 'admin'@'localhost' тут было 'admin'@'%'?
Ответ
DEFINER просто говорит базе, какой контекст безопасности использовать при выполнении процедуры. Если он стоит как DEFINER - привилегии берутся для аккаунта, который создал процедуру, а если стоит INVOKER - то тогда привилегии, как у того, кто вызвал. CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1()
SQL SECURITY DEFINER
BEGIN
UPDATE t1 SET counter = counter + 1;
END;
Любой пользователь, который имеет привилегию EXECUTE на над процедурой p1 может вызвать ее с помощью оператора CALL. Однако, когда p1 выполняется, она делает это в контексте безопасности DEFINER и, следовательно, выполняется с привилегиями 'admin'@'localhost' , учетной записи, указанной в атрибуте DEFINER. Эта учетная запись должна иметь привилегию EXECUTE для p1 , а также UPDATE привилегии для таблицы t1 . В противном случае, процедура не выполняется из-за отсутствия достаточных привилегий. Адрес говорит вам о том, что будут использованы привелегии определенные для пользователя 'admin'@'localhost. Тоесть пользователя admin который подключается с localhost, в MYSQL разграничение доступа осуществляется по имени пользователя и адресу с которого идет подключение, для пользователя admin с localhost можно установить GRANT ALL а для других хостов только SELECT например. Пользователи 'admin'@'localhost' и 'admin'@'%' - это совершенно разные аккаунты.
Есть лендинг с фиксированным хедером. Нужно чтобы в нем отображалась полоса прогресса скроллинга по странице, а именно по разделам. Как это осуществить?
Ответ
var
bar = $('#bar'),
$window = $(window),
docHeight = $(document).height(),
winHeight = $window.height(),
baseX = docHeight - winHeight;
$window.scroll(function(e) {
var x = ($window.scrollTop() / baseX) * 100;
bar.css({'width': + x + '%'});
});
body{
height:4000px;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
overflow: hidden;
}
a {
text-decoration: none;
}
ul li {
display: block;
float: left;
}
ul li a {
display: block;
padding: 1rem 2rem;
font-family: sans-serif;
}
.nav {
display: block;
width: 100%;
border-bottom: 2px solid #ccc;
position: relative;
position: fixed;
}
#bar{
position:absolute;
left: 0;
bottom: -2px;
background-color:red;
width: 0px;
height: 2px;
}
Вариант с якорями:
var
bar = $('#bar'),
$window = $(window),
docHeight = $(document).height(),
winHeight = $window.height(),
baseX = docHeight - winHeight;
var
lastId,
topNav = $(".nav"),
topNavHeight = topNav.outerHeight(),
link = topNav.find("a");
scrollItems = link.map(function(){
var item = $($(this).attr("href"));
if (item.length) { return item; }
});
$window.scroll(function(e) {
var x = ($window.scrollTop() / baseX) * 100;
bar.css({'width': + x + '%'});
var fromTop = $(this).scrollTop()+topNavHeight;
var cur = scrollItems.map(function(){
if ($(this).offset().top < fromTop)
return this;
});
cur = cur[cur.length-1];
var id = cur && cur.length ? cur[0].id : "";
if (lastId !== id) {
lastId = id;
link
.parent().removeClass("active")
.end().filter("[href='#"+id+"']").parent().addClass("active");
}
});
body{
height:4000px;
padding-top: 5rem;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
overflow: hidden;
}
a {
text-decoration: none;
}
ul li {
display: block;
float: left;
}
ul li a {
display: block;
padding: 1rem 2rem;
font-family: sans-serif;
}
.nav {
display: block;
width: 100%;
border-bottom: 2px solid #ccc;
position: relative;
position: fixed;
top: 0;
}
#bar{
position:absolute;
left: 0;
bottom: -2px;
background-color:red;
width: 0px;
height: 2px;
}
.box {
height: 20rem;
padding: 2rem;
line-height: 1.5rem;
}
.active a{
background: red;
color: #fff;
}
1 Lorem ipsum dolor sit amet, consectetur adipisicing elit. A, excepturi.
2 Lorem ipsum dolor sit amet.
3 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Temporibus, at debitis! Fuga, architecto, illum. Deleniti optio voluptatibus suscipit veniam, dicta.
Задача такая: отучить KDE автостартовать приложения, которые были запущены в предыдущей сессии. Сами приложения не прописаны в автозапуске, KDE их запускает сам. Искал по всем настройкам, в гугле, ответа не нашел. Как отучить KDE автозапускать последние приложения?
Ответ
Оказалось, эта настройка запрятана в "Управлении сеансами", что в разделе "Запуск и завершение". Мне и в голову не могло придти искать эту функцию там, так как я считал, что сеансы связаны исключительно с входом нескольких пользователей в систему. Итого,что бы отключить эту фитчу идем в "Параметры системы" -> "Запуск и завершение" -> "Управление сеансами" и ставим "Начинать с пустого сеанса".
Было разработано приложение с использованием WPF. Заказчик использует приложение на планшете и интерфейс мелковат для быстрой работы, требуется увеличить все элементы, ну скажем, на 50%. Как сделать это быстро и с меньшими затратами? В каждом Window применить к контейнеру компоновки трансформацию Scale в RenderTransform? Попробовал сделать это на примере одного из Window - окно и не знает, что содержимое увеличилось и оно в окно не влезает... Как всё-таки правильно это сделать? На что при этом обратить внимание? А, может быть, есть способ сделать масштабирование динамическим с возможностью смены коэффициента во время работы (при работе с мышью ведь увеличение и не требуется)?
Ответ
Ну, если решать проблему так, как вы хотите (масштабированием интерфейса), то подойдёт следующая идея. Пусть вы увеличиваете всё в k раз (у вас k = 1.5). Пишем так:
(С удивлением обнаружил, что RenderTransform перемещает область hit test.)
Однако мне кажется, что это не идеальное решение. Дело в том, что простое скалирование интерфейса не поможет. Майкрософт пробовала в ранних версиях Windows Phone скалирование десктопных интерфейсов, и отказалась от этого: при таком подходе страдает usability. Когда у вас мало места на экране, вы захотите не скалировать всё, а расположить элементы по-другому. Поэтому лучше следовать опыту Microsoft, и сделать для планшетов отдельный интерфейс, похожий на основной, но «заточенный» под меньший размер экрана и тач-управление. Будет выглядеть намного профессиональнее.
Дополнение: Если вам нужно менять размер в зависимости от разных обстоятельств, проще всего сделать его параметром. Это делается так:
В MainWindow кладём DependencyProperty типа double, назовём его ScalseFactor. Значение по умолчанию — 1.0 public double ScaleFactor
{
get { return (double)GetValue(ScaleFactorProperty); }
set { SetValue(ScaleFactorProperty, value); }
} public static readonly DependencyProperty ScaleFactorProperty =
DependencyProperty.Register(
"ScaleFactor", typeof(double), typeof(MainWindow), new PropertyMetadata(1.0));
Вместо константы 1.5 в ScaleY прописываем привязку: {Binding ScaleFactor, ElementName=Main}
(даём окну имя Main, чтобы было проще привязывать).
Для привязки ColumnDefinition нам нужно вычесть единицу и перейти от double к типу GridLength, поэтому используем конвертер. Для начала определим его: class RestGridLengthConverter : IValueConverter
{
public object Convert(object value, Type tt, object parameter, CultureInfo ci)
{
return new GridLength((double)value - 1, GridUnitType.Star);
} public object ConvertBack(object value, Type tt, object parameter, CultureInfo ci)
{
throw new NotImplementedException();
}
}
Кладём в ресурсы и привязываем:
Всё, теперь у нас можно настраивать увеличение при старте программы (или вообще когда угодно), используя ScaleFactor
Например, можно прикрутить к нему слайдер. Вот полный пример:
namespace Example
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} public double ScaleFactor
{
get { return (double)GetValue(ScaleFactorProperty); }
set { SetValue(ScaleFactorProperty, value); }
} public static readonly DependencyProperty ScaleFactorProperty =
DependencyProperty.Register(
"ScaleFactor", typeof(double), typeof(MainWindow), new PropertyMetadata(1.0));
}
}
namespace Example
{
class RestGridLengthConverter : IValueConverter
{
public object Convert(object value, Type tt, object parameter, CultureInfo ci)
{
return new GridLength((double)value - 1, GridUnitType.Star);
} public object ConvertBack(object value, Type tt, object parameter, CultureInfo ci)
{
throw new NotImplementedException();
}
}
}
Результат:
Есть функция которая отвечает за перемещение, кружочка по тач-событиям. Но проблема в том, что курсор то обгоняет сам кружочек то отстает. Как сделать так, чтоб кружочек двигался равномерно, вслед за пальцем при этом не обгонял и не отставал ? Сам код :
var target;
$('.circle').on("touchstart", function() {
target = $(this);
});
var moove = function (obj, x, y){
$(obj).css({"left" : x });
$(obj).css({"top" : y });
}
$(window).on("touchmove", function(e) {
moove($(target), event.targetTouches[0].screenX, event.targetTouches[0].screenY );
});
.circle {
width: 50px;
height: 50px;
border-radius: 100%;
background: green;
position: absolute;
}
фидл: https://jsfiddle.net/dxnxpybe/21/
Ответ
А Вы пробовали изменить screenX и screenY на clientX clientY, вроде как кружочек следует за пальцем. var target; $('.circle').on("touchstart", function() {
target = $(this);
}); var moove = function (obj, x, y){
$(obj).css({"left" : x });
$(obj).css({"top" : y });
} $(window).on("touchmove", function(e) {
moove($(target), event.targetTouches[0].clientX, event.targetTouches[0].clientY );
});
https://jsfiddle.net/appcscme/1/