Merge pull request #153 from poisdeux/sharedelementtransition_addons

Implemented shared element transitions for addons
This commit is contained in:
Synced Synapse 2015-12-16 19:36:31 +00:00
commit 8f71f4e2dc
5 changed files with 164 additions and 103 deletions

View File

@ -15,6 +15,7 @@
*/ */
package org.xbmc.kore.ui; package org.xbmc.kore.ui;
import android.annotation.TargetApi;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.os.Bundle; import android.os.Bundle;
@ -39,9 +40,9 @@ import org.xbmc.kore.host.HostInfo;
import org.xbmc.kore.host.HostManager; import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.jsonrpc.ApiCallback; import org.xbmc.kore.jsonrpc.ApiCallback;
import org.xbmc.kore.jsonrpc.method.Addons; import org.xbmc.kore.jsonrpc.method.Addons;
import org.xbmc.kore.jsonrpc.type.AddonType;
import org.xbmc.kore.utils.LogUtils; import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.UIUtils; import org.xbmc.kore.utils.UIUtils;
import org.xbmc.kore.utils.Utils;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.InjectView; import butterknife.InjectView;
@ -53,7 +54,16 @@ import butterknife.OnClick;
public class AddonDetailsFragment extends Fragment { public class AddonDetailsFragment extends Fragment {
private static final String TAG = LogUtils.makeLogTag(AddonDetailsFragment.class); private static final String TAG = LogUtils.makeLogTag(AddonDetailsFragment.class);
public static final String ADDONID = "addon_id"; public static final String BUNDLE_KEY_ADDONID = "addon_id";
public static final String POSTER_TRANS_NAME = "POSTER_TRANS_NAME";
public static final String BUNDLE_KEY_NAME = "name";
public static final String BUNDLE_KEY_AUTHOR = "author";
public static final String BUNDLE_KEY_SUMMARY = "summary";
public static final String BUNDLE_KEY_VERSION = "version";
public static final String BUNDLE_KEY_DESCRIPTION = "description";
public static final String BUNDLE_KEY_FANART = "fanart";
public static final String BUNDLE_KEY_POSTER = "poster";
public static final String BUNDLE_KEY_ENABLED = "enabled";
private HostManager hostManager; private HostManager hostManager;
private HostInfo hostInfo; private HostInfo hostInfo;
@ -87,11 +97,24 @@ public class AddonDetailsFragment extends Fragment {
/** /**
* Create a new instance of this, initialized to show the addon addonId * Create a new instance of this, initialized to show the addon addonId
*/ */
public static AddonDetailsFragment newInstance(String addonId) { @TargetApi(21)
public static AddonDetailsFragment newInstance(AddonListFragment.ViewHolder vh) {
AddonDetailsFragment fragment = new AddonDetailsFragment(); AddonDetailsFragment fragment = new AddonDetailsFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(ADDONID, addonId); args.putString(BUNDLE_KEY_ADDONID, vh.addonId);
args.putString(BUNDLE_KEY_NAME, vh.addonName);
args.putString(BUNDLE_KEY_AUTHOR, vh.author);
args.putString(BUNDLE_KEY_VERSION, vh.version);
args.putString(BUNDLE_KEY_SUMMARY, vh.summary);
args.putString(BUNDLE_KEY_DESCRIPTION, vh.description);
args.putString(BUNDLE_KEY_FANART, vh.fanart);
args.putString(BUNDLE_KEY_POSTER, vh.poster);
args.putBoolean(BUNDLE_KEY_ENABLED, vh.enabled);
if( Utils.isLollipopOrLater()) {
args.putString(POSTER_TRANS_NAME, vh.artView.getTransitionName());
}
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@ -101,9 +124,11 @@ public class AddonDetailsFragment extends Fragment {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
@TargetApi(21)
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
addonId = getArguments().getString(ADDONID, null); Bundle bundle = getArguments();
addonId = bundle.getString(BUNDLE_KEY_ADDONID, null);
if ((container == null) || (addonId == null)) { if ((container == null) || (addonId == null)) {
// We're not being shown or there's nothing to show // We're not being shown or there's nothing to show
@ -131,6 +156,20 @@ public class AddonDetailsFragment extends Fragment {
FloatingActionButton fab = (FloatingActionButton)fabButton; FloatingActionButton fab = (FloatingActionButton)fabButton;
fab.attachToScrollView((ObservableScrollView) mediaPanel); fab.attachToScrollView((ObservableScrollView) mediaPanel);
if(Utils.isLollipopOrLater()) {
mediaPoster.setTransitionName(bundle.getString(POSTER_TRANS_NAME));
}
mediaTitle.setText(bundle.getString(BUNDLE_KEY_NAME));
mediaUndertitle.setText(bundle.getString(BUNDLE_KEY_SUMMARY));
mediaAuthor.setText(bundle.getString(BUNDLE_KEY_AUTHOR));
mediaVersion.setText(bundle.getString(BUNDLE_KEY_VERSION));
mediaDescription.setText(bundle.getString(BUNDLE_KEY_DESCRIPTION));
setImages(bundle.getString(BUNDLE_KEY_POSTER), bundle.getString(BUNDLE_KEY_FANART));
setupEnableButton(bundle.getBoolean(BUNDLE_KEY_ENABLED, false));
// Pad main content view to overlap with bottom system bar // Pad main content view to overlap with bottom system bar
// UIUtils.setPaddingForSystemBars(getActivity(), mediaPanel, false, false, true); // UIUtils.setPaddingForSystemBars(getActivity(), mediaPanel, false, false, true);
// mediaPanel.setClipToPadding(false); // mediaPanel.setClipToPadding(false);
@ -142,31 +181,6 @@ public class AddonDetailsFragment extends Fragment {
public void onActivityCreated (Bundle savedInstanceState) { public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(false); setHasOptionsMenu(false);
// Get the addon details, this is done asyhnchronously
String[] properties = new String[] {
AddonType.Fields.NAME, AddonType.Fields.VERSION, AddonType.Fields.SUMMARY,
AddonType.Fields.DESCRIPTION, AddonType.Fields.PATH, AddonType.Fields.AUTHOR,
AddonType.Fields.THUMBNAIL, AddonType.Fields.DISCLAIMER, AddonType.Fields.FANART,
//AddonType.Fields.DEPENDENCIES, AddonType.Fields.BROKEN, AddonType.Fields.EXTRAINFO,
AddonType.Fields.RATING, AddonType.Fields.ENABLED
};
Addons.GetAddonDetails action = new Addons.GetAddonDetails(addonId, properties);
action.execute(hostManager.getConnection(), new ApiCallback<AddonType.Details>() {
@Override
public void onSuccess(AddonType.Details result) {
if (!isAdded()) return;
displayAddonDetails(result);
}
@Override
public void onError(int errorCode, String description) {
if (!isAdded()) return;
Toast.makeText(getActivity(),
String.format(getString(R.string.error_getting_addon_info), description),
Toast.LENGTH_SHORT).show();
}
}, callbackHandler);
} }
@Override @Override
@ -225,70 +239,39 @@ public class AddonDetailsFragment extends Fragment {
public void onError(int errorCode, String description) { public void onError(int errorCode, String description) {
if (!isAdded()) return; if (!isAdded()) return;
Toast.makeText(getActivity(), Toast.makeText(getActivity(),
String.format(getString(R.string.general_error_executing_action), description), String.format(getString(R.string.general_error_executing_action), description),
Toast.LENGTH_SHORT) Toast.LENGTH_SHORT)
.show(); .show();
} }
}, callbackHandler); }, callbackHandler);
} }
/** private void setImages(String poster, String fanart) {
* Display the addon details
*
* @param addonDetails Addon details
*/
private void displayAddonDetails(AddonType.Details addonDetails) {
mediaTitle.setText(addonDetails.name);
mediaUndertitle.setText(addonDetails.summary);
mediaAuthor.setText(addonDetails.author);
mediaVersion.setText(addonDetails.version);
mediaDescription.setText(addonDetails.description);
// Images
Resources resources = getActivity().getResources(); Resources resources = getActivity().getResources();
DisplayMetrics displayMetrics = new DisplayMetrics(); DisplayMetrics displayMetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int artHeight = resources.getDimensionPixelOffset(R.dimen.now_playing_art_height), int artHeight = resources.getDimensionPixelOffset(R.dimen.now_playing_art_height),
artWidth = displayMetrics.widthPixels; artWidth = displayMetrics.widthPixels;
if (!TextUtils.isEmpty(addonDetails.fanart)) { int posterWidth = resources.getDimensionPixelOffset(R.dimen.addondetail_poster_width);
int posterWidth = resources.getDimensionPixelOffset(R.dimen.addondetail_poster_width); int posterHeight = resources.getDimensionPixelOffset(R.dimen.addondetail_poster_height);
int posterHeight = resources.getDimensionPixelOffset(R.dimen.addondetail_poster_heigth);
mediaPoster.setVisibility(View.VISIBLE); UIUtils.loadImageIntoImageview(hostManager,
UIUtils.loadImageIntoImageview(hostManager, TextUtils.isEmpty(fanart)? poster : fanart,
addonDetails.thumbnail, mediaArt, artWidth, artHeight);
mediaPoster, posterWidth, posterHeight); UIUtils.loadImageIntoImageview(hostManager,
UIUtils.loadImageIntoImageview(hostManager, poster,
addonDetails.fanart, mediaPoster, posterWidth, posterHeight);
mediaArt, artWidth, artHeight);
} else {
// No fanart, just present the poster
mediaPoster.setVisibility(View.GONE);
UIUtils.loadImageIntoImageview(hostManager,
addonDetails.thumbnail,
mediaArt, artWidth, artHeight);
// Reset padding
int paddingLeft = mediaTitle.getPaddingRight(),
paddingRight = mediaTitle.getPaddingRight(),
paddingTop = mediaTitle.getPaddingTop(),
paddingBottom = mediaTitle.getPaddingBottom();
mediaTitle.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
mediaUndertitle.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
}
setupEnableButton(addonDetails.enabled);
} }
private void setupEnableButton(boolean enabled) { private void setupEnableButton(boolean enabled) {
// Enabled button // Enabled button
if (enabled) { if (enabled) {
Resources.Theme theme = getActivity().getTheme(); Resources.Theme theme = getActivity().getTheme();
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] { TypedArray styledAttributes = theme.obtainStyledAttributes(new int[]{
R.attr.colorAccent}); R.attr.colorAccent});
enabledButton.setColorFilter(styledAttributes.getColor(0, enabledButton.setColorFilter(styledAttributes.getColor(0,
getActivity().getResources().getColor(R.color.accent_default))); getActivity().getResources().getColor(R.color.accent_default)));
styledAttributes.recycle(); styledAttributes.recycle();
fabButton.setVisibility(View.VISIBLE); fabButton.setVisibility(View.VISIBLE);
@ -298,4 +281,16 @@ public class AddonDetailsFragment extends Fragment {
} }
enabledButton.setTag(enabled); enabledButton.setTag(enabled);
} }
/**
* Returns the shared element if visible
* @return View if visible, null otherwise
*/
public View getSharedElement() {
if (UIUtils.isViewInBounds(mediaPanel, mediaPoster)) {
return mediaPoster;
}
return null;
}
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.xbmc.kore.ui; package org.xbmc.kore.ui;
import android.annotation.TargetApi;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
@ -39,6 +40,7 @@ import org.xbmc.kore.jsonrpc.method.Addons;
import org.xbmc.kore.jsonrpc.type.AddonType; import org.xbmc.kore.jsonrpc.type.AddonType;
import org.xbmc.kore.utils.LogUtils; import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.UIUtils; import org.xbmc.kore.utils.UIUtils;
import org.xbmc.kore.utils.Utils;
import java.util.List; import java.util.List;
@ -53,7 +55,7 @@ public class AddonListFragment extends Fragment
private static final String TAG = LogUtils.makeLogTag(AddonListFragment.class); private static final String TAG = LogUtils.makeLogTag(AddonListFragment.class);
public interface OnAddonSelectedListener { public interface OnAddonSelectedListener {
public void onAddonSelected(String addonId, String addonTitle); public void onAddonSelected(ViewHolder vh);
} }
// Activity listener // Activity listener
@ -99,7 +101,7 @@ public class AddonListFragment extends Fragment
// Get the movie id from the tag // Get the movie id from the tag
ViewHolder tag = (ViewHolder) view.getTag(); ViewHolder tag = (ViewHolder) view.getTag();
// Notify the activity // Notify the activity
listenerActivity.onAddonSelected(tag.addonId, tag.addonName); listenerActivity.onAddonSelected(tag);
} }
}); });
@ -210,8 +212,8 @@ public class AddonListFragment extends Fragment
// To prevent the empty text from appearing on the first load, set it now // To prevent the empty text from appearing on the first load, set it now
emptyView.setText(getString(R.string.no_addons_found_refresh)); emptyView.setText(getString(R.string.no_addons_found_refresh));
Toast.makeText(getActivity(), Toast.makeText(getActivity(),
String.format(getString(R.string.error_getting_addon_info), description), String.format(getString(R.string.error_getting_addon_info), description),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setRefreshing(false);
} }
}, callbackHandler); }, callbackHandler);
@ -230,13 +232,12 @@ public class AddonListFragment extends Fragment
// Use the same dimensions as in the details fragment, so that it hits Picasso's cache when // Use the same dimensions as in the details fragment, so that it hits Picasso's cache when
// the user transitions to that fragment, avoiding another call and imediatelly showing the image // the user transitions to that fragment, avoiding another call and imediatelly showing the image
Resources resources = context.getResources(); Resources resources = context.getResources();
artWidth = (int)(resources.getDimension(R.dimen.addondetail_poster_width) / artWidth = resources.getDimensionPixelOffset(R.dimen.addondetail_poster_width);;
UIUtils.IMAGE_RESIZE_FACTOR); artHeight = resources.getDimensionPixelOffset(R.dimen.addondetail_poster_height);;
artHeight = (int)(resources.getDimension(R.dimen.addondetail_poster_heigth) /
UIUtils.IMAGE_RESIZE_FACTOR);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@TargetApi(21)
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) { if (convertView == null) {
@ -257,13 +258,24 @@ public class AddonListFragment extends Fragment
// Save the movie id // Save the movie id
viewHolder.addonId = addonDetails.addonid; viewHolder.addonId = addonDetails.addonid;
viewHolder.addonName = addonDetails.name; viewHolder.addonName = addonDetails.name;
viewHolder.author = addonDetails.author;
viewHolder.description = addonDetails.description;
viewHolder.summary = addonDetails.summary;
viewHolder.version = addonDetails.version;
viewHolder.fanart = addonDetails.fanart;
viewHolder.poster = addonDetails.thumbnail;
viewHolder.enabled = addonDetails.enabled;
viewHolder.titleView.setText(viewHolder.addonName); viewHolder.titleView.setText(viewHolder.addonName);
viewHolder.detailsView.setText(addonDetails.summary); viewHolder.detailsView.setText(addonDetails.summary);
UIUtils.loadImageWithCharacterAvatar(getContext(), hostManager, UIUtils.loadImageWithCharacterAvatar(getContext(), hostManager,
addonDetails.thumbnail, viewHolder.addonName, addonDetails.thumbnail, viewHolder.addonName,
viewHolder.artView, artWidth, artHeight); viewHolder.artView, artWidth, artHeight);
if(Utils.isLollipopOrLater()) {
viewHolder.artView.setTransitionName("a"+viewHolder.addonId);
}
return convertView; return convertView;
} }
} }
@ -271,12 +283,19 @@ public class AddonListFragment extends Fragment
/** /**
* View holder pattern * View holder pattern
*/ */
private static class ViewHolder { public static class ViewHolder {
TextView titleView; TextView titleView;
TextView detailsView; TextView detailsView;
ImageView artView; ImageView artView;
String addonId; String addonId;
String addonName; String addonName;
String summary;
String author;
String version;
String description;
String fanart;
String poster;
Boolean enabled;
} }
} }

View File

@ -22,15 +22,20 @@ import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.transition.Transition;
import android.transition.TransitionInflater; import android.transition.TransitionInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import android.view.Window; import android.view.Window;
import org.xbmc.kore.R; import org.xbmc.kore.R;
import org.xbmc.kore.utils.LogUtils; import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.Utils; import org.xbmc.kore.utils.Utils;
import java.util.List;
import java.util.Map;
/** /**
* Controls the presentation of Addons information (list, details) * Controls the presentation of Addons information (list, details)
* All the information is presented by specific fragments * All the information is presented by specific fragments
@ -47,6 +52,8 @@ public class AddonsActivity extends BaseActivity
private NavigationDrawerFragment navigationDrawerFragment; private NavigationDrawerFragment navigationDrawerFragment;
private boolean clearSharedElements;
@TargetApi(21) @TargetApi(21)
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -67,10 +74,26 @@ public class AddonsActivity extends BaseActivity
// Setup animations // Setup animations
if (Utils.isLollipopOrLater()) { if (Utils.isLollipopOrLater()) {
addonListFragment.setExitTransition(null); //Fade added to prevent shared element from disappearing very shortly at the start of the transition.
addonListFragment.setReenterTransition(TransitionInflater Transition fade = TransitionInflater
.from(this) .from(this)
.inflateTransition(android.R.transition.fade)); .inflateTransition(android.R.transition.fade);
addonListFragment.setExitTransition(fade);
addonListFragment.setReenterTransition(fade);
addonListFragment.setSharedElementReturnTransition(TransitionInflater.from(
this).inflateTransition(R.transition.change_image));
android.support.v4.app.SharedElementCallback seCallback = new android.support.v4.app.SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
if (clearSharedElements) {
names.clear();
sharedElements.clear();
clearSharedElements = false;
}
}
};
addonListFragment.setExitSharedElementCallback(seCallback);
} }
getSupportFragmentManager() getSupportFragmentManager()
.beginTransaction() .beginTransaction()
@ -175,32 +198,56 @@ public class AddonsActivity extends BaseActivity
/** /**
* Callback from list fragment when a addon is selected. * Callback from list fragment when a addon is selected.
* Switch fragment in portrait * Switch fragment in portrait
* @param addonId Addon selected * @param vh
* @param addonTitle Title
*/ */
@TargetApi(21) @TargetApi(21)
public void onAddonSelected(String addonId, String addonTitle) { public void onAddonSelected(AddonListFragment.ViewHolder vh) {
selectedAddonId = addonId; selectedAddonId = vh.addonId;
selectedAddonTitle = addonTitle; selectedAddonTitle = vh.addonName;
// Replace list fragment // Replace list fragment
AddonDetailsFragment addonDetailsFragment = AddonDetailsFragment.newInstance(addonId); final AddonDetailsFragment addonDetailsFragment = AddonDetailsFragment.newInstance(vh);
FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction(); FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction();
// Set up transitions // Set up transitions
if (Utils.isLollipopOrLater()) { if (Utils.isLollipopOrLater()) {
android.support.v4.app.SharedElementCallback seCallback = new android.support.v4.app.SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
//On returning onMapSharedElements for the exiting fragment is called before the onMapSharedElements
// for the reentering fragment. We use this to determine if we are returning and if
// we should clear the shared element lists. Note that, clearing must be done in the reentering fragment
// as this is called last. Otherwise it the app will crash during transition setup. Not sure, but might
// be a v4 support package bug.
if (addonDetailsFragment.isVisible()) {
View sharedView = addonDetailsFragment.getSharedElement();
if (sharedView == null) { // shared element not visible
clearSharedElements = true;
}
}
}
};
addonDetailsFragment.setEnterSharedElementCallback(seCallback);
addonDetailsFragment.setEnterTransition(TransitionInflater addonDetailsFragment.setEnterTransition(TransitionInflater
.from(this) .from(this)
.inflateTransition(R.transition.media_details)); .inflateTransition(R.transition.media_details));
addonDetailsFragment.setReturnTransition(null); addonDetailsFragment.setReturnTransition(null);
Transition changeImageTransition = TransitionInflater.from(
this).inflateTransition(R.transition.change_image);
addonDetailsFragment.setSharedElementReturnTransition(changeImageTransition);
addonDetailsFragment.setSharedElementEnterTransition(changeImageTransition);
fragTrans.addSharedElement(vh.artView, vh.artView.getTransitionName());
} else { } else {
fragTrans.setCustomAnimations(R.anim.fragment_details_enter, 0, fragTrans.setCustomAnimations(R.anim.fragment_details_enter, 0,
R.anim.fragment_list_popenter, 0); R.anim.fragment_list_popenter, 0);
} }
fragTrans.replace(R.id.fragment_container, addonDetailsFragment) fragTrans.replace(R.id.fragment_container, addonDetailsFragment)
.addToBackStack(null) .addToBackStack(null)
.commit(); .commit();
setupActionBar(selectedAddonTitle); setupActionBar(selectedAddonTitle);
} }

View File

@ -69,7 +69,7 @@
<dimen name="addonlist_art_heigth">88dp</dimen> <dimen name="addonlist_art_heigth">88dp</dimen>
<dimen name="addondetail_poster_width">146dp</dimen> <dimen name="addondetail_poster_width">146dp</dimen>
<dimen name="addondetail_poster_heigth">146dp</dimen> <dimen name="addondetail_poster_height">146dp</dimen>
<dimen name="channellist_art_width">88dp</dimen> <dimen name="channellist_art_width">88dp</dimen>
<dimen name="channellist_art_heigth">88dp</dimen> <dimen name="channellist_art_heigth">88dp</dimen>

View File

@ -114,7 +114,7 @@
<dimen name="addonlist_art_heigth">74dp</dimen> <dimen name="addonlist_art_heigth">74dp</dimen>
<dimen name="addondetail_poster_width">112dp</dimen> <dimen name="addondetail_poster_width">112dp</dimen>
<dimen name="addondetail_poster_heigth">112dp</dimen> <dimen name="addondetail_poster_height">112dp</dimen>
<dimen name="filelist_art_width">52dp</dimen> <dimen name="filelist_art_width">52dp</dimen>
<dimen name="filelist_art_heigth">76dp</dimen> <dimen name="filelist_art_heigth">76dp</dimen>