Added counts for collapsed folders. Add slight backgorund for the listview.

This commit is contained in:
RyanBateman 2012-07-12 20:25:35 -04:00
parent c03c168af3
commit c752f0c148
17 changed files with 222 additions and 90 deletions

View file

@ -3,7 +3,7 @@
<item>
<bitmap
android:src="@drawable/second_repeating_pattern"
android:src="@drawable/repeating_pattern"
android:tileMode="repeat"
/>
</item>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<bitmap
android:src="@drawable/second_repeating_pattern"
android:tileMode="repeat"
/>
</item>
<item>
<shape>
<solid android:color="@color/half_lightgray" />
</shape>
</item>
</layer-list>

View file

@ -4,5 +4,5 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:dividerHeight="1px"
android:background="@drawable/list_background"
/>

View file

@ -1,24 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="@color/lightgray">
<ImageView
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/lightgray"
android:paddingBottom="10dp"
android:paddingTop="10dp" >
<ImageView
android:id="@+id/row_folder_icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_width="20dp"
android:src="@drawable/folder"
android:layout_margin="10dp"
android:contentDescription="@string/description_row_folder_icon"/>
<TextView
android:id="@+id/row_foldername"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_margin="10dp"
android:contentDescription="@string/description_row_folder_icon"
android:src="@drawable/folder" />
<TextView
android:id="@+id/row_foldername"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/row_folder_icon"
android:textColor="@color/darkgray"
android:textSize="16dp"
android:textStyle="bold"
android:gravity="center_vertical"
android:textColor="@color/darkgray" />
</LinearLayout>
android:textStyle="bold" />
<LinearLayout
android:id="@+id/row_foldersums"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="25dp" >
<TextView
android:id="@+id/row_foldersumneg"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="10dp"
android:background="@drawable/negative_count_circle"
android:gravity="center"
android:textColor="@color/white"
android:textSize="12dp"
android:textStyle="bold" />
<TextView
android:id="@+id/row_foldersumneu"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="10dp"
android:background="@drawable/neutral_count_circle"
android:gravity="center"
android:textColor="@color/white"
android:textSize="12dp"
android:textStyle="bold" />
<TextView
android:id="@+id/row_foldersumpos"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/positive_count_circle"
android:gravity="center"
android:layout_marginRight="10dp"
android:textColor="@color/white"
android:textSize="12dp"
android:textStyle="bold" />
</LinearLayout>
</RelativeLayout>

View file

@ -1,23 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="@color/lightgray">
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/folder"
android:layout_margin="10dp" android:contentDescription="@string/description_row_folder_icon"/>
<TextView
android:id="@+id/row_foldername"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/lightgray" >
<ImageView
android:id="@+id/row_folder_icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentLeft="true"
android:layout_margin="10dp"
android:contentDescription="@string/description_row_folder_icon"
android:src="@drawable/folder" />
<TextView
android:id="@+id/row_foldername"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_toRightOf="@id/row_folder_icon"
android:textColor="@color/darkgray"
android:textSize="16dp"
android:textStyle="bold"
android:layout_marginLeft="30dp"
android:textColor="@color/darkgray" />
</LinearLayout>
android:textStyle="bold" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:layout_marginRight="35dp" >
<TextView
android:id="@+id/row_foldersumpos"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="@color/darkgray"
android:textSize="5dp"
android:textStyle="bold" />
</LinearLayout>
</RelativeLayout>

View file

@ -13,6 +13,7 @@
<color name="half_black">#7000</color>
<color name="transparent">#0000</color>
<color name="half_darkgray">#77434343</color>
<color name="half_lightgray">#77dddddd</color>
<color name="positive">#3B7613</color>
<color name="neutral">#F6C000</color>

View file

@ -12,6 +12,7 @@ import android.view.Window;
import com.newsblur.R;
import com.newsblur.fragment.LoginFragment;
import com.newsblur.network.APIConstants;
import com.newsblur.util.PrefConstants;
public class Login extends FragmentActivity implements LoginFragment.LoginFragmentInterface {

View file

@ -52,8 +52,13 @@ public class DatabaseConstants {
public static final String STORY_READ = "read";
public static final String STORY_FEED_ID = "feed_id";
// Aggregated columns
public static final String SUM_POS = "sum_postive";
public static final String SUM_NEUT = "sum_neutral";
public static final String SUM_NEG = "sum_negative";
public static final String[] FOLDER_COLUMNS = {
FOLDER_TABLE + "." + FOLDER_ID, FOLDER_TABLE + "." + FOLDER_NAME
FOLDER_TABLE + "." + FOLDER_ID, FOLDER_TABLE + "." + FOLDER_NAME, " SUM(" + FEED_POSITIVE_COUNT + ") AS " + SUM_POS, " SUM(" + FEED_NEUTRAL_COUNT + ") AS " + SUM_NEUT, " SUM(" + FEED_NEGATIVE_COUNT + ") AS " + SUM_NEG
};
}

View file

@ -114,6 +114,7 @@ public class FeedProvider extends ContentProvider {
final SQLiteDatabase db = databaseHelper.getReadableDatabase();
Cursor cursor = null;
switch (uriMatcher.match(uri)) {
// Query for all feeds (by default only return those that have unread items in them)
case ALL_FEEDS:
cursor = db.rawQuery("SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
@ -122,23 +123,31 @@ public class FeedProvider extends ContentProvider {
" WHERE (" + DatabaseConstants.FEED_NEGATIVE_COUNT + " + " + DatabaseConstants.FEED_NEUTRAL_COUNT + " + " + DatabaseConstants.FEED_POSITIVE_COUNT + ") > 0 " +
" ORDER BY " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_TITLE + " COLLATE NOCASE", selectionArgs);
break;
// Querying for a specific
case SPECIFIC_FEED:
selection = DatabaseConstants.FEED_ID + " = ?";
selectionArgs = new String[] { uri.getLastPathSegment() };
cursor = db.query(DatabaseConstants.FEED_TABLE, projection, selection, selectionArgs, null, null, sortOrder);
break;
// Query for feeds with no folder mapping
case FEED_FOLDER_MAP:
cursor = db.rawQuery("SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_TABLE +
" LEFT JOIN " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
" ON " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_ID + " = " + DatabaseConstants.FEED_FOLDER_MAP_TABLE + "." + DatabaseConstants.FEED_FOLDER_FEED_ID +
" WHERE " + DatabaseConstants.FEED_FOLDER_MAP_TABLE + "." + DatabaseConstants.FEED_FOLDER_FOLDER_NAME + " IS NULL AND " +
" (" + DatabaseConstants.FEED_NEGATIVE_COUNT + " + " + DatabaseConstants.FEED_NEUTRAL_COUNT + " + " + DatabaseConstants.FEED_POSITIVE_COUNT + ") > 0 ", null);
String nullFolderQuery = "SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_TABLE +
" LEFT JOIN " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
" ON " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_ID + " = " + DatabaseConstants.FEED_FOLDER_MAP_TABLE + "." + DatabaseConstants.FEED_FOLDER_FEED_ID +
" WHERE " + DatabaseConstants.FEED_FOLDER_MAP_TABLE + "." + DatabaseConstants.FEED_FOLDER_FOLDER_NAME + " IS NULL " +
" GROUP BY " + DatabaseConstants.FEED_TABLE+ "." + DatabaseConstants.FEED_ID;
StringBuilder nullFolderBuilder = new StringBuilder();
nullFolderBuilder.append(nullFolderQuery);
if (selectionArgs != null && selectionArgs.length > 0) {
nullFolderBuilder.append(selectionArgs[0]);
}
nullFolderBuilder.append(" ORDER BY " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_TITLE + " COLLATE NOCASE");
cursor = db.rawQuery(nullFolderBuilder.toString(), null);
break;
// Querying for feeds for a given folder
case SPECIFIC_FEED_FOLDER_MAP:
selection = DatabaseConstants.FOLDER_ID + " = ?";
@ -148,7 +157,7 @@ public class FeedProvider extends ContentProvider {
" INNER JOIN " + DatabaseConstants.FEED_TABLE +
" ON " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_ID + " = " + DatabaseConstants.FEED_FOLDER_MAP_TABLE + "." + DatabaseConstants.FEED_FOLDER_FEED_ID +
" WHERE " + DatabaseConstants.FEED_FOLDER_MAP_TABLE + "." + DatabaseConstants.FEED_FOLDER_FOLDER_NAME + " = ? " +
" GROUP BY " + DatabaseConstants.FEED_TABLE+ "." + DatabaseConstants.FOLDER_ID;
" GROUP BY " + DatabaseConstants.FEED_TABLE+ "." + DatabaseConstants.FEED_ID;
StringBuilder builder = new StringBuilder();
builder.append(query);
@ -158,7 +167,7 @@ public class FeedProvider extends ContentProvider {
builder.append(" ORDER BY " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_TITLE + " COLLATE NOCASE");
cursor = db.rawQuery(builder.toString(), folderArguments);
break;
// Querying for all folders with unread items
case ALL_FOLDERS:
String folderQuery = "SELECT " + TextUtils.join(",", DatabaseConstants.FOLDER_COLUMNS) + " FROM " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +

View file

@ -1,7 +1,5 @@
package com.newsblur.database;
import com.newsblur.domain.Folder;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
@ -9,13 +7,16 @@ import android.net.Uri;
import android.text.TextUtils;
import android.widget.SimpleCursorTreeAdapter;
import com.newsblur.domain.Folder;
public class FolderTreeAdapter extends SimpleCursorTreeAdapter {
ContentResolver resolver;
public String currentState = FeedProvider.INTELLIGENCE_ALL;
private String TAG = "FolderTreeAdapter";
public FolderTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout, int expandedGroupLayout, String[] groupFrom, int[] groupTo, int childLayout, String[] childFrom, int[] childTo) {
super(context, cursor, collapsedGroupLayout, expandedGroupLayout, groupFrom, groupTo, childLayout, childFrom, childTo);
public FolderTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout, String[] groupFrom, int[] groupTo, int childLayout, String[] childFrom, int[] childTo) {
super(context, cursor, collapsedGroupLayout, groupFrom, groupTo, childLayout, childFrom, childTo);
resolver = context.getContentResolver();
}

View file

@ -9,33 +9,41 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnGroupClickListener;
import com.newsblur.R;
import com.newsblur.database.DatabaseConstants;
import com.newsblur.database.FeedProvider;
import com.newsblur.database.FolderTreeAdapter;
import com.newsblur.util.AppConstants;
import com.newsblur.util.UIUtils;
import com.newsblur.view.FolderTreeViewBinder;
import com.newsblur.view.StateToggleButton;
public class FolderFeedListFragment extends Fragment {
public class FolderFeedListFragment extends Fragment implements OnGroupClickListener {
private ExpandableListView list;
private ContentResolver resolver;
private FolderTreeAdapter folderAdapter;
private FolderTreeViewBinder viewBinder;
private int leftBound, rightBound;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
resolver = getActivity().getContentResolver();
Cursor cursor = resolver.query(FeedProvider.FOLDERS_URI, null, null, null, null);
final String[] groupFrom = new String[] { DatabaseConstants.FOLDER_NAME };
final int[] groupTo = new int[] { R.id.row_foldername };
viewBinder = new FolderTreeViewBinder();
leftBound = UIUtils.convertDPsToPixels(getActivity(), 20);
rightBound = UIUtils.convertDPsToPixels(getActivity(), 10);
final String[] groupFrom = new String[] { DatabaseConstants.FOLDER_NAME, DatabaseConstants.SUM_POS, DatabaseConstants.SUM_NEG, DatabaseConstants.SUM_NEUT };
final int[] groupTo = new int[] { R.id.row_foldername, R.id.row_foldersumpos, R.id.row_foldersumneg, R.id.row_foldersumneu };
final String[] childFrom = new String[] { DatabaseConstants.FEED_TITLE, DatabaseConstants.FEED_FAVICON, DatabaseConstants.FEED_NEUTRAL_COUNT, DatabaseConstants.FEED_NEGATIVE_COUNT, DatabaseConstants.FEED_POSITIVE_COUNT };
final int[] childTo = new int[] { R.id.row_feedname, R.id.row_feedfavicon, R.id.row_feedneutral, R.id.row_feednegative, R.id.row_feedpositive };
folderAdapter = new FolderTreeAdapter(getActivity(), cursor, R.layout.row_folder_collapsed, R.layout.row_folder_expanded, groupFrom, groupTo, R.layout.row_feed, childFrom, childTo);
folderAdapter.setViewBinder(new FolderTreeViewBinder());
folderAdapter = new FolderTreeAdapter(getActivity(), cursor, R.layout.row_folder_collapsed, groupFrom, groupTo, R.layout.row_feed, childFrom, childTo);
folderAdapter.setViewBinder(viewBinder);
}
@Override
@ -45,25 +53,27 @@ public class FolderFeedListFragment extends Fragment {
Display display = getActivity().getWindowManager().getDefaultDisplay();
int width = display.getWidth();
list.setIndicatorBounds(width - 50, width - 10);
list.setIndicatorBounds(width - leftBound, width - rightBound);
list.setChildDivider(getActivity().getResources().getDrawable(R.drawable.divider_light));
list.setAdapter(folderAdapter);
list.setOnGroupClickListener(this);
return v;
}
public void changeState(int state) {
String selection = null;
viewBinder.setState(state);
switch (state) {
case (StateToggleButton.STATE_ONE):
case (AppConstants.STATE_ALL):
selection = FeedProvider.INTELLIGENCE_ALL;
break;
case (StateToggleButton.STATE_TWO):
case (AppConstants.STATE_SOME):
selection = FeedProvider.INTELLIGENCE_SOME;
break;
case (StateToggleButton.STATE_THREE):
case (AppConstants.STATE_BEST):
selection = FeedProvider.INTELLIGENCE_BEST;
break;
}
@ -74,4 +84,14 @@ public class FolderFeedListFragment extends Fragment {
folderAdapter.notifyDataSetChanged();
}
@Override
public boolean onGroupClick(ExpandableListView list, View group, int groupPosition, long id) {
if (list.isGroupExpanded(groupPosition)) {
group.findViewById(R.id.row_foldersums).setVisibility(View.VISIBLE);
} else {
group.findViewById(R.id.row_foldersums).setVisibility(View.INVISIBLE);
}
return false;
}
}

View file

@ -12,7 +12,7 @@ import java.util.List;
import java.util.Map.Entry;
import java.util.Scanner;
import com.newsblur.activity.PrefConstants;
import com.newsblur.util.PrefConstants;
import android.content.ContentValues;
import android.content.Context;

View file

@ -0,0 +1,7 @@
package com.newsblur.util;
public class AppConstants {
public static final int STATE_ALL = 0;
public static final int STATE_SOME = 1;
public static final int STATE_BEST = 2;
}

View file

@ -1,4 +1,4 @@
package com.newsblur.activity;
package com.newsblur.util;
public class PrefConstants {

View file

@ -14,7 +14,6 @@ import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import com.newsblur.activity.PrefConstants;
import com.newsblur.domain.UserProfile;
public class PrefsUtil {

View file

@ -12,9 +12,14 @@ import android.widget.TextView;
import com.newsblur.R;
import com.newsblur.database.DatabaseConstants;
import com.newsblur.util.AppConstants;
public class FolderTreeViewBinder implements ViewBinder {
private int currentState = AppConstants.STATE_ALL;
// TODO: Make this more efficient
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (TextUtils.equals(cursor.getColumnName(columnIndex), DatabaseConstants.FEED_FAVICON)) {
@ -28,7 +33,7 @@ public class FolderTreeViewBinder implements ViewBinder {
}
((ImageView) view).setImageBitmap(bitmap);
return true;
} else if (TextUtils.equals(cursor.getColumnName(columnIndex), DatabaseConstants.FEED_POSITIVE_COUNT)) {
} else if (TextUtils.equals(cursor.getColumnName(columnIndex), DatabaseConstants.FEED_POSITIVE_COUNT) || TextUtils.equals(cursor.getColumnName(columnIndex), DatabaseConstants.SUM_POS)) {
int feedPositive = cursor.getInt(columnIndex);
if (feedPositive > 0) {
view.setVisibility(View.VISIBLE);
@ -37,18 +42,18 @@ public class FolderTreeViewBinder implements ViewBinder {
view.setVisibility(View.GONE);
}
return true;
} else if (TextUtils.equals(cursor.getColumnName(columnIndex), DatabaseConstants.FEED_NEUTRAL_COUNT)) {
} else if (TextUtils.equals(cursor.getColumnName(columnIndex), DatabaseConstants.FEED_NEUTRAL_COUNT) || TextUtils.equals(cursor.getColumnName(columnIndex), DatabaseConstants.SUM_NEUT)) {
int feedNeutral = cursor.getInt(columnIndex);
if (feedNeutral > 0) {
if (feedNeutral > 0 && currentState != AppConstants.STATE_BEST) {
view.setVisibility(View.VISIBLE);
((TextView) view).setText("" + feedNeutral);
} else {
view.setVisibility(View.GONE);
}
return true;
} else if (TextUtils.equals(cursor.getColumnName(columnIndex), DatabaseConstants.FEED_NEGATIVE_COUNT)) {
} else if (TextUtils.equals(cursor.getColumnName(columnIndex), DatabaseConstants.FEED_NEGATIVE_COUNT) || TextUtils.equals(cursor.getColumnName(columnIndex), DatabaseConstants.SUM_NEG)) {
int feedNegative = cursor.getInt(columnIndex);
if (feedNegative > 0) {
if (feedNegative > 0 && currentState == AppConstants.STATE_ALL) {
view.setVisibility(View.VISIBLE);
((TextView) view).setText("" + feedNegative);
} else {
@ -65,7 +70,12 @@ public class FolderTreeViewBinder implements ViewBinder {
((TextView) view).setText("" + folderName);
return true;
}
return false;
}
public void setState(int selection) {
currentState = selection;
}
}

View file

@ -8,14 +8,12 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import com.newsblur.R;
import com.newsblur.util.AppConstants;
import com.newsblur.util.UIUtils;
public class StateToggleButton extends LinearLayout implements OnClickListener {
public static final int STATE_ONE = 0;
public static final int STATE_TWO = 1;
public static final int STATE_THREE = 2;
private int CURRENT_STATE = STATE_ONE;
private int CURRENT_STATE = AppConstants.STATE_ALL;
private Context context;
private StateChangedListener stateChangedListener;
@ -39,19 +37,19 @@ public class StateToggleButton extends LinearLayout implements OnClickListener {
final int marginTop = UIUtils.convertDPsToPixels(context, 5);
imageStateOne = new ImageView(context);
imageStateOne.setId(STATE_ONE);
imageStateOne.setId(AppConstants.STATE_ALL);
imageStateOne.setImageResource(R.drawable.negative_count_circle);
imageStateOne.setLayoutParams(new LayoutParams(length, length));
LayoutParams centerParams = new LayoutParams(length, length);
centerParams.setMargins(marginSide, marginTop, marginSide, marginTop);
imageStateTwo = new ImageView(context);
imageStateTwo.setId(STATE_TWO);
imageStateTwo.setId(AppConstants.STATE_SOME);
imageStateTwo.setImageResource(R.drawable.neutral_count_circle);
imageStateTwo.setLayoutParams(centerParams);
imageStateThree = new ImageView(context);
imageStateThree.setId(STATE_THREE);
imageStateThree.setId(AppConstants.STATE_BEST);
imageStateThree.setImageResource(R.drawable.positive_count_circle);
imageStateThree.setLayoutParams(new LayoutParams(length, length));
@ -73,17 +71,17 @@ public class StateToggleButton extends LinearLayout implements OnClickListener {
public void changeState(final int state) {
switch (state) {
case STATE_ONE:
case AppConstants.STATE_ALL:
imageStateOne.setAlpha(255);
imageStateTwo.setAlpha(125);
imageStateThree.setAlpha(125);
break;
case STATE_TWO:
case AppConstants.STATE_SOME:
imageStateOne.setAlpha(125);
imageStateTwo.setAlpha(255);
imageStateThree.setAlpha(125);
break;
case STATE_THREE:
case AppConstants.STATE_BEST:
imageStateOne.setAlpha(125);
imageStateTwo.setAlpha(125);
imageStateThree.setAlpha(255);