Skip to content

Commit

Permalink
feat(android): display drag handle for movable rows
Browse files Browse the repository at this point in the history
  • Loading branch information
garymathews authored and sgtcoolguy committed Jan 19, 2021
1 parent be522d6 commit 8d79902
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 144 deletions.
10 changes: 10 additions & 0 deletions android/modules/ui/res/drawable/titanium_icon_drag.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#C3C3C3">
<path
android:fillColor="@android:color/black"
android:pathData="M20,9H4v2h16V9zM4,15h16v-2H4V15z"/>
</vector>
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,14 @@ public void selectRow(int index)
}
}

@Override
public void onPropertyChanged(String name, Object value)
{
super.onPropertyChanged(name, value);

processProperty(name, value);
}

/**
* Handle setting of property.
*
Expand All @@ -690,9 +698,27 @@ public void setProperty(String name, Object value)
{
super.setProperty(name, value);

processProperty(name, value);
}

/**
* Process property set on proxy.
*
* @param name Property name.
* @param value Property value.
*/
private void processProperty(String name, Object value)
{
if (name.equals(TiC.PROPERTY_DATA) || name.equals(TiC.PROPERTY_SECTIONS)) {
setData((Object[]) value);
}

if (name.equals(TiC.PROPERTY_EDITING)
|| name.equals(TiC.PROPERTY_MOVING)) {

// Update table to display drag-handles.
update();
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ public void onPropertyChanged(String name, Object value)
*/
private void processProperty(String name, Object value)
{
final TableViewProxy tableViewProxy = getTableViewProxy();

if (name.equals(TiC.PROPERTY_SELECTED_BACKGROUND_COLOR)) {
Log.w(TAG, "selectedBackgroundColor is deprecated, use backgroundSelectedColor instead.");
setProperty(TiC.PROPERTY_BACKGROUND_SELECTED_COLOR, value);
Expand Down Expand Up @@ -392,7 +394,8 @@ private void processProperty(String name, Object value)
|| name.equals(TiC.PROPERTY_LEFT)
|| name.equals(TiC.PROPERTY_RIGHT)
|| name.equals(TiC.PROPERTY_TOP)
|| name.equals(TiC.PROPERTY_BOTTOM)) {
|| name.equals(TiC.PROPERTY_BOTTOM)
|| name.equals(TiC.PROPERTY_MOVABLE)) {

// Force re-bind of row.
invalidate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,10 @@ private void processProperty(String name, Object value)
Log.w(TAG, "selectedBackgroundImage is deprecated, use backgroundSelectedImage instead.");
setProperty(TiC.PROPERTY_BACKGROUND_SELECTED_IMAGE, value);
}

if (name.equals(TiC.PROPERTY_CAN_MOVE)) {
invalidate();
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
package ti.modules.titanium.ui.widget.listview;

import org.appcelerator.kroll.KrollDict;
import org.appcelerator.kroll.common.Log;
import org.appcelerator.titanium.R;
import org.appcelerator.titanium.TiApplication;
import org.appcelerator.titanium.TiC;
import org.appcelerator.titanium.TiDimension;
import org.appcelerator.titanium.proxy.TiViewProxy;
import org.appcelerator.titanium.util.TiConvert;
import org.appcelerator.titanium.util.TiFileHelper;
import org.appcelerator.titanium.util.TiRHelper;
import org.appcelerator.titanium.util.TiUIHelper;
import org.appcelerator.titanium.view.TiCompositeLayout;
Expand Down Expand Up @@ -44,85 +42,23 @@
public class ListViewHolder extends TiRecyclerViewHolder
{
private static final String TAG = "ListViewHolder";
private static final int COLOR_GRAY = Color.rgb(169, 169, 169);

private static Drawable checkDrawable;
private static Drawable disclosureDrawable;
private static TiFileHelper fileHelper;
private static Drawable moreDrawable;
private static Resources resources;
private static int selectableItemBackgroundId = 0;
// Top
private final ViewGroup header;
private final TextView headerTitle;

// Middle
private final ViewGroup container;
private final TiCompositeLayout content;
private final ImageView rightImage;

// Bottom
private final TiCompositeLayout footer;
private final TextView footerTitle;
// Top
private final TiCompositeLayout header;
private final TextView headerTitle;
private final ImageView rightImage;

public ListViewHolder(final Context context, final ViewGroup viewGroup)
{
super(viewGroup);

if (resources == null) {

// Obtain resources instance.
resources = context.getResources();
}
if (resources != null) {

// Attempt to load `icon_more` drawable.
if (moreDrawable == null) {
try {
final int icon_more_id = R.drawable.titanium_icon_more;
moreDrawable = resources.getDrawable(icon_more_id);
} catch (Exception e) {
Log.w(TAG, "Drawable 'drawable.icon_more' not found.");
}
}

// Attempt to load `icon_checkmark` drawable.
if (checkDrawable == null) {
try {
final int icon_checkmark_id = R.drawable.titanium_icon_checkmark;
checkDrawable = resources.getDrawable(icon_checkmark_id);
} catch (Exception e) {
Log.w(TAG, "Drawable 'drawable.icon_checkmark' not found.");
}
}

// Attempt to load `icon_disclosure` drawable.
if (disclosureDrawable == null) {
try {
final int icon_disclosure_id = R.drawable.titanium_icon_disclosure;
disclosureDrawable = resources.getDrawable(icon_disclosure_id);
} catch (Exception e) {
Log.w(TAG, "Drawable 'drawable.icon_disclosure' not found.");
}
}

if (selectableItemBackgroundId == 0) {
try {
final TypedValue selectableItemBackgroundValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
selectableItemBackgroundValue, true);
selectableItemBackgroundId = selectableItemBackgroundValue.resourceId;
} catch (Exception e) {
Log.w(TAG, "Drawable for default background not found.");
}
}
} else {
Log.w(TAG, "Could not obtain context resources instance.");
}
if (fileHelper == null) {

// Obtain file helper instance.
fileHelper = new TiFileHelper(context);
}
super(context, viewGroup);

// Obtain views from identifiers.
this.header = viewGroup.findViewById(R.id.titanium_ui_listview_holder_header);
Expand Down Expand Up @@ -164,6 +100,7 @@ public void bind(final ListItemProxy proxy, final boolean selected)
if (listViewProxy == null) {
return;
}
final KrollDict listViewProperties = listViewProxy.getProperties();

// Attempt to obtain parent section proxy is available.
final ListSectionProxy section =
Expand Down Expand Up @@ -196,6 +133,15 @@ public void bind(final ListItemProxy proxy, final boolean selected)
}
}

// Display drag drawable when item can move.
final boolean isEditing = listViewProperties.optBoolean(TiC.PROPERTY_EDITING, false);
final boolean canMove = properties.optBoolean(TiC.PROPERTY_CAN_MOVE,
listViewProperties.optBoolean(TiC.PROPERTY_CAN_MOVE, false));
if (isEditing && canMove) {
this.rightImage.setImageDrawable(dragDrawable);
this.rightImage.setVisibility(View.VISIBLE);
}

if (proxy != null) {
final TiUIView view = proxy.getOrCreateView();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,14 @@ public boolean isFiltered()
return false;
}

@Override
public void onPropertyChanged(String name, Object value)
{
super.onPropertyChanged(name, value);

processProperty(name, value);
}

/**
* Handle setting of property.
*
Expand All @@ -317,11 +325,28 @@ public void setProperty(String name, Object value)
{
super.setProperty(name, value);

processProperty(name, value);
}

/**
* Process property set on proxy.
*
* @param name Property name.
* @param value Property value.
*/
private void processProperty(String name, Object value)
{
if (name.equals(TiC.PROPERTY_SECTIONS)) {

// Set list sections.
setSections((Object[]) value);
}

if (name.equals(TiC.PROPERTY_EDITING)) {

// Update list to display drag-handles.
update();
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,109 @@
*/
package ti.modules.titanium.ui.widget.listview;

import android.view.View;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import org.appcelerator.kroll.common.Log;
import org.appcelerator.titanium.R;
import org.appcelerator.titanium.proxy.TiViewProxy;
import org.appcelerator.titanium.util.TiFileHelper;

import java.lang.ref.WeakReference;

public abstract class TiRecyclerViewHolder extends RecyclerView.ViewHolder
{
private static final String TAG = "TiRecyclerViewHolder";

protected static final int COLOR_GRAY = Color.rgb(169, 169, 169);

protected static Drawable checkDrawable;
protected static Drawable disclosureDrawable;
protected static Drawable dragDrawable;
protected static Drawable moreDrawable;

protected static Resources resources;
protected static TiFileHelper fileHelper;

protected static int selectableItemBackgroundId = 0;

protected WeakReference<TiViewProxy> proxy;

public TiRecyclerViewHolder(@NonNull View itemView)
public TiRecyclerViewHolder(final Context context, final ViewGroup viewGroup)
{
super(itemView);
super(viewGroup);

if (resources == null) {

// Obtain resources instance.
resources = context.getResources();
}
if (resources != null) {

// Attempt to load `titanium_icon_more` drawable.
if (moreDrawable == null) {
try {
final int icon_more_id = R.drawable.titanium_icon_more;
moreDrawable = resources.getDrawable(icon_more_id);
} catch (Exception e) {
Log.w(TAG, "Drawable 'drawable.titanium_icon_more' not found.");
}
}

// Attempt to load `titanium_icon_checkmark` drawable.
if (checkDrawable == null) {
try {
final int icon_checkmark_id = R.drawable.titanium_icon_checkmark;
checkDrawable = resources.getDrawable(icon_checkmark_id);
} catch (Exception e) {
Log.w(TAG, "Drawable 'drawable.titanium_icon_checkmark' not found.");
}
}

// Attempt to load `titanium_icon_disclosure` drawable.
if (disclosureDrawable == null) {
try {
final int icon_disclosure_id = R.drawable.titanium_icon_disclosure;
disclosureDrawable = resources.getDrawable(icon_disclosure_id);
} catch (Exception e) {
Log.w(TAG, "Drawable 'drawable.titanium_icon_disclosure' not found.");
}
}

// Attempt to load `titanium_icon_drag` drawable.
if (dragDrawable == null) {
try {
final int icon_drag_id = R.drawable.titanium_icon_drag;
dragDrawable = resources.getDrawable(icon_drag_id);
} catch (Exception e) {
Log.w(TAG, "Drawable 'drawable.titanium_icon_drag' not found.");
}
}

if (selectableItemBackgroundId == 0) {
try {
final TypedValue selectableItemBackgroundValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackgroundBorderless,
selectableItemBackgroundValue, true);
selectableItemBackgroundId = selectableItemBackgroundValue.resourceId;
} catch (Exception e) {
Log.w(TAG, "Drawable for default background not found.");
}
}
} else {
Log.w(TAG, "Could not obtain context resources instance.");
}
if (fileHelper == null) {

// Obtain file helper instance.
fileHelper = new TiFileHelper(context);
}
}

/**
Expand Down
Loading

0 comments on commit 8d79902

Please sign in to comment.