画面下部にカラム一覧。カラム設定に色と背景。他タンスのハッシュタグを疑似アカウントで開く
This commit is contained in:
parent
e8529e4c1b
commit
23c5c9d572
|
@ -9,8 +9,8 @@ android {
|
|||
applicationId "jp.juggler.subwaytooter"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 39
|
||||
versionName "0.3.9"
|
||||
versionCode 40
|
||||
versionName "0.4.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
|
|
@ -130,8 +130,13 @@
|
|||
<activity
|
||||
android:name=".ActMutedApp"
|
||||
android:label="@string/muted_app"
|
||||
|
||||
/>
|
||||
|
||||
<activity
|
||||
android:name=".ActColumnCustomize"
|
||||
android:label="@string/color_and_background"
|
||||
/>
|
||||
|
||||
<activity
|
||||
android:name=".ActNickname"
|
||||
android:label="@string/nickname_and_color"
|
||||
|
|
|
@ -375,7 +375,7 @@ public class ActAccountSetting extends AppCompatActivity
|
|||
}
|
||||
} );
|
||||
progress.show();
|
||||
AsyncTaskCompat.executeParallel( task );
|
||||
task.executeOnExecutor(App1.task_executor);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,309 @@
|
|||
package jp.juggler.subwaytooter;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.jrummyapps.android.colorpicker.ColorPickerDialog;
|
||||
import com.jrummyapps.android.colorpicker.ColorPickerDialogListener;
|
||||
|
||||
import jp.juggler.subwaytooter.util.LogCategory;
|
||||
import jp.juggler.subwaytooter.util.Utils;
|
||||
|
||||
public class ActColumnCustomize extends AppCompatActivity
|
||||
implements View.OnClickListener, ColorPickerDialogListener
|
||||
{
|
||||
static final LogCategory log = new LogCategory( "ActColumnCustomize" );
|
||||
|
||||
static final String EXTRA_COLUMN_INDEX = "column_index";
|
||||
|
||||
public static void open( ActMain activity, int idx, int request_code ){
|
||||
Intent intent = new Intent( activity, ActColumnCustomize.class );
|
||||
intent.putExtra( EXTRA_COLUMN_INDEX, idx );
|
||||
activity.startActivityForResult( intent, request_code );
|
||||
|
||||
}
|
||||
|
||||
@Override public void onBackPressed(){
|
||||
makeResult();
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
private void makeResult(){
|
||||
Intent data = new Intent();
|
||||
data.putExtra( EXTRA_COLUMN_INDEX, column_index );
|
||||
setResult( RESULT_OK ,data);
|
||||
}
|
||||
|
||||
int column_index;
|
||||
Column column;
|
||||
AppState app_state;
|
||||
float density;
|
||||
|
||||
@Override protected void onCreate( @Nullable Bundle savedInstanceState ){
|
||||
super.onCreate( savedInstanceState );
|
||||
App1.setActivityTheme( this, false );
|
||||
initUI();
|
||||
|
||||
app_state = App1.getAppState( this );
|
||||
density = app_state.density;
|
||||
column_index = getIntent().getIntExtra( EXTRA_COLUMN_INDEX, 0 );
|
||||
column = app_state.column_list.get( column_index );
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
@Override protected void onDestroy(){
|
||||
closeBitmaps();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
static final int COLOR_DIALOG_ID_HEADER_BACKGROUND = 1;
|
||||
static final int COLOR_DIALOG_ID_HEADER_FOREGROUND = 2;
|
||||
static final int COLOR_DIALOG_ID_COLUMN_BACKGROUND = 3;
|
||||
|
||||
@Override public void onClick( View v ){
|
||||
ColorPickerDialog.Builder builder;
|
||||
switch( v.getId() ){
|
||||
|
||||
case R.id.btnHeaderBackgroundEdit:
|
||||
builder = ColorPickerDialog.newBuilder()
|
||||
.setDialogType( ColorPickerDialog.TYPE_CUSTOM )
|
||||
.setAllowPresets( true )
|
||||
.setShowAlphaSlider( false )
|
||||
.setDialogId( COLOR_DIALOG_ID_HEADER_BACKGROUND )
|
||||
;
|
||||
if( column.header_bg_color != 0 ) builder.setColor( column.header_bg_color );
|
||||
builder.show( this );
|
||||
break;
|
||||
|
||||
case R.id.btnHeaderBackgroundReset:
|
||||
column.header_bg_color = 0;
|
||||
show();
|
||||
break;
|
||||
|
||||
case R.id.btnHeaderTextEdit:
|
||||
builder = ColorPickerDialog.newBuilder()
|
||||
.setDialogType( ColorPickerDialog.TYPE_CUSTOM )
|
||||
.setAllowPresets( true )
|
||||
.setShowAlphaSlider( false )
|
||||
.setDialogId( COLOR_DIALOG_ID_HEADER_FOREGROUND )
|
||||
;
|
||||
if( column.header_fg_color != 0 ) builder.setColor( column.header_fg_color );
|
||||
builder.show( this );
|
||||
break;
|
||||
|
||||
case R.id.btnHeaderTextReset:
|
||||
column.header_fg_color = 0;
|
||||
show();
|
||||
break;
|
||||
|
||||
case R.id.btnColumnBackgroundColor:
|
||||
builder = ColorPickerDialog.newBuilder()
|
||||
.setDialogType( ColorPickerDialog.TYPE_CUSTOM )
|
||||
.setAllowPresets( true )
|
||||
.setShowAlphaSlider( false )
|
||||
.setDialogId( COLOR_DIALOG_ID_COLUMN_BACKGROUND )
|
||||
;
|
||||
if( column.column_bg_color != 0 ) builder.setColor( column.column_bg_color );
|
||||
builder.show( this );
|
||||
break;
|
||||
|
||||
case R.id.btnColumnBackgroundColorReset:
|
||||
column.column_bg_color = 0;
|
||||
show();
|
||||
break;
|
||||
|
||||
case R.id.btnColumnBackgroundImage:
|
||||
Intent intent = new Intent( Intent.ACTION_OPEN_DOCUMENT );
|
||||
intent.addCategory( Intent.CATEGORY_OPENABLE );
|
||||
intent.setType( "image/*" );
|
||||
startActivityForResult( intent, REQUEST_CODE_PICK_BACKGROUND );
|
||||
break;
|
||||
|
||||
case R.id.btnColumnBackgroundImageReset:
|
||||
column.column_bg_image = null;
|
||||
show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onColorSelected( int dialogId, @ColorInt int color ){
|
||||
switch( dialogId ){
|
||||
case COLOR_DIALOG_ID_HEADER_BACKGROUND:
|
||||
column.header_bg_color = 0xff000000 | color;
|
||||
break;
|
||||
case COLOR_DIALOG_ID_HEADER_FOREGROUND:
|
||||
column.header_fg_color = 0xff000000 | color;
|
||||
break;
|
||||
case COLOR_DIALOG_ID_COLUMN_BACKGROUND:
|
||||
column.column_bg_color = 0xff000000 | color;
|
||||
break;
|
||||
}
|
||||
show();
|
||||
}
|
||||
|
||||
@Override public void onDialogDismissed( int dialogId ){
|
||||
}
|
||||
|
||||
static final int REQUEST_CODE_PICK_BACKGROUND = 1;
|
||||
|
||||
@Override protected void onActivityResult( int requestCode, int resultCode, Intent data ){
|
||||
if( requestCode == REQUEST_CODE_PICK_BACKGROUND && resultCode == RESULT_OK ){
|
||||
if( data != null ){
|
||||
Uri uri = data.getData();
|
||||
if( uri != null ){
|
||||
getContentResolver().takePersistableUriPermission( uri, Intent.FLAG_GRANT_READ_URI_PERMISSION );
|
||||
column.column_bg_image = uri.toString();
|
||||
show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
View flColumnBackground;
|
||||
ImageView ivColumnBackground;
|
||||
SeekBar sbColumnBackgroundAlpha;
|
||||
View llColumnHeader;
|
||||
ImageView ivColumnHeader;
|
||||
TextView tvColumnName;
|
||||
|
||||
|
||||
static final int PROGRESS_MAX = 65536;
|
||||
|
||||
private void initUI(){
|
||||
setContentView( R.layout.act_column_customize );
|
||||
|
||||
findViewById( R.id.btnHeaderBackgroundEdit ).setOnClickListener( this );
|
||||
findViewById( R.id.btnHeaderBackgroundReset ).setOnClickListener( this );
|
||||
findViewById( R.id.btnHeaderTextEdit ).setOnClickListener( this );
|
||||
findViewById( R.id.btnHeaderTextReset ).setOnClickListener( this );
|
||||
findViewById( R.id.btnColumnBackgroundColor ).setOnClickListener( this );
|
||||
findViewById( R.id.btnColumnBackgroundColorReset ).setOnClickListener( this );
|
||||
findViewById( R.id.btnColumnBackgroundImage ).setOnClickListener( this );
|
||||
findViewById( R.id.btnColumnBackgroundImageReset ).setOnClickListener( this );
|
||||
|
||||
|
||||
llColumnHeader = findViewById( R.id.llColumnHeader );
|
||||
ivColumnHeader = (ImageView) findViewById( R.id.ivColumnHeader );
|
||||
tvColumnName = (TextView) findViewById( R.id.tvColumnName );
|
||||
|
||||
flColumnBackground = findViewById( R.id.flColumnBackground );
|
||||
ivColumnBackground = (ImageView) findViewById( R.id.ivColumnBackground );
|
||||
|
||||
sbColumnBackgroundAlpha = (SeekBar) findViewById( R.id.sbColumnBackgroundAlpha );
|
||||
sbColumnBackgroundAlpha.setMax( PROGRESS_MAX );
|
||||
|
||||
sbColumnBackgroundAlpha.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override public void onStartTrackingTouch( SeekBar seekBar ){
|
||||
}
|
||||
|
||||
@Override public void onStopTrackingTouch( SeekBar seekBar ){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged( SeekBar seekBar, int progress, boolean fromUser ){
|
||||
if( fromUser ){
|
||||
column.column_bg_image_alpha = progress / (float)PROGRESS_MAX;
|
||||
ivColumnBackground.setAlpha( column.column_bg_image_alpha );
|
||||
}
|
||||
}
|
||||
|
||||
} );
|
||||
}
|
||||
|
||||
private void show(){
|
||||
int c = column.header_bg_color;
|
||||
if( c == 0 ){
|
||||
llColumnHeader.setBackgroundResource( R.drawable.btn_bg_ddd );
|
||||
}else{
|
||||
ViewCompat.setBackground( llColumnHeader,Styler.getAdaptiveRippleDrawable(
|
||||
c,
|
||||
(column.header_fg_color != 0 ? column.header_fg_color :
|
||||
Styler.getAttributeColor( this,R.attr.colorRippleEffect ))
|
||||
) );
|
||||
}
|
||||
|
||||
c = column.header_fg_color;
|
||||
if( c == 0 ){
|
||||
tvColumnName.setTextColor( Styler.getAttributeColor( this, android.R.attr.textColorPrimary ) );
|
||||
Styler.setIconDefaultColor( this, ivColumnHeader, Column.getIconAttrId( column.column_type ) );
|
||||
}else{
|
||||
tvColumnName.setTextColor( c );
|
||||
Styler.setIconCustomColor( this, ivColumnHeader, c, Column.getIconAttrId( column.column_type ) );
|
||||
}
|
||||
|
||||
tvColumnName.setText( column.getColumnName( false ));
|
||||
|
||||
if( column.column_bg_color != 0 ){
|
||||
flColumnBackground.setBackgroundColor( column.column_bg_color );
|
||||
}else{
|
||||
ViewCompat.setBackground( flColumnBackground, null );
|
||||
}
|
||||
|
||||
float alpha =column.column_bg_image_alpha;
|
||||
if( Float.isNaN( alpha )){
|
||||
alpha = column.column_bg_image_alpha = 1f;
|
||||
}
|
||||
ivColumnBackground.setAlpha( alpha );
|
||||
sbColumnBackgroundAlpha.setProgress( (int) ( 0.5f + alpha * PROGRESS_MAX ) );
|
||||
|
||||
loadImage( ivColumnBackground, column.column_bg_image );
|
||||
}
|
||||
|
||||
String last_image_uri;
|
||||
Bitmap last_image_bitmap;
|
||||
|
||||
private void closeBitmaps(){
|
||||
try{
|
||||
ivColumnBackground.setImageDrawable( null );
|
||||
last_image_uri = null;
|
||||
if( last_image_bitmap != null ){
|
||||
last_image_bitmap.recycle();
|
||||
last_image_bitmap = null;
|
||||
}
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void loadImage( ImageView ivColumnBackground, String url ){
|
||||
try{
|
||||
if( TextUtils.isEmpty(url ) ){
|
||||
closeBitmaps();
|
||||
return;
|
||||
|
||||
}else if( url.equals( last_image_uri ) ){
|
||||
// 今表示してるのと同じ
|
||||
return;
|
||||
}
|
||||
|
||||
// 直前のBitmapを掃除する
|
||||
closeBitmaps();
|
||||
|
||||
// 画像をロードして、成功したら表示してURLを覚える
|
||||
int resize_max = (int) ( 0.5f + 64f * density );
|
||||
Uri uri = Uri.parse( url );
|
||||
last_image_bitmap = Utils.createResizedBitmap( log, this, uri,false, resize_max );
|
||||
if( last_image_bitmap != null ){
|
||||
ivColumnBackground.setImageBitmap( last_image_bitmap );
|
||||
last_image_uri = url;
|
||||
}
|
||||
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import android.os.Bundle;
|
|||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
import android.support.v4.os.AsyncTaskCompat;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.TextUtils;
|
||||
|
@ -25,8 +25,10 @@ import android.support.v7.app.AppCompatActivity;
|
|||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.Window;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
@ -59,7 +61,7 @@ import okhttp3.Request;
|
|||
import okhttp3.RequestBody;
|
||||
|
||||
public class ActMain extends AppCompatActivity
|
||||
implements NavigationView.OnNavigationItemSelectedListener
|
||||
implements NavigationView.OnNavigationItemSelectedListener, View.OnClickListener, ViewPager.OnPageChangeListener
|
||||
{
|
||||
public static final LogCategory log = new LogCategory( "ActMain" );
|
||||
|
||||
|
@ -93,11 +95,13 @@ public class ActMain extends AppCompatActivity
|
|||
this.density = app_state.density;
|
||||
this.acct_pad_lr = (int) ( 0.5f + 4f * density );
|
||||
|
||||
|
||||
initUI();
|
||||
|
||||
updateColumnStrip();
|
||||
|
||||
if( pager_adapter.column_list.size() > 0 ){
|
||||
llEmpty.setVisibility( View.GONE );
|
||||
onPageSelected( pager.getCurrentItem() );
|
||||
}
|
||||
|
||||
AlarmService.startCheck( this );
|
||||
|
@ -129,6 +133,7 @@ public class ActMain extends AppCompatActivity
|
|||
if( bRemoved ){
|
||||
pager_adapter.setOrder( pager, new_order );
|
||||
app_state.saveColumnList();
|
||||
updateColumnStrip();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +170,7 @@ public class ActMain extends AppCompatActivity
|
|||
private void handleSentIntent( final Intent sent_intent ){
|
||||
AccountPicker.pick( this, false, true, getString( R.string.account_picker_toot ), new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
ActPost.open( ActMain.this,REQUEST_CODE_POST,ai.db_id,sent_intent);
|
||||
ActPost.open( ActMain.this, REQUEST_CODE_POST, ai.db_id, sent_intent );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
@ -189,6 +194,44 @@ public class ActMain extends AppCompatActivity
|
|||
super.onPause();
|
||||
}
|
||||
|
||||
@Override public void onClick( View v ){
|
||||
switch( v.getId() ){
|
||||
case R.id.btnMenu:
|
||||
if( ! drawer.isDrawerOpen( Gravity.START ) ){
|
||||
drawer.openDrawer( Gravity.START );
|
||||
}
|
||||
break;
|
||||
|
||||
case R.id.btnToot:
|
||||
performTootButton();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled( int position, float positionOffset, int positionOffsetPixels ){
|
||||
|
||||
}
|
||||
|
||||
@Override public void onPageSelected( final int position ){
|
||||
handler.post( new Runnable() {
|
||||
@Override public void run(){
|
||||
if( position >= 0 && position < app_state.column_list.size() ){
|
||||
Column column = app_state.column_list.get( position );
|
||||
if( ! column.bFirstInitialized ){
|
||||
column.startLoading();
|
||||
}
|
||||
scrollColumnStrip( position );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Override public void onPageScrollStateChanged( int state ){
|
||||
|
||||
}
|
||||
|
||||
boolean isOrderChanged( ArrayList< Integer > new_order ){
|
||||
if( new_order.size() != pager_adapter.getCount() ) return true;
|
||||
for( int i = 0, ie = new_order.size() ; i < ie ; ++ i ){
|
||||
|
@ -202,6 +245,7 @@ public class ActMain extends AppCompatActivity
|
|||
static final int REQUEST_APP_ABOUT = 3;
|
||||
static final int REQUEST_CODE_NICKNAME = 4;
|
||||
static final int REQUEST_CODE_POST = 5;
|
||||
static final int REQUEST_COLUMN_COLOR = 6;
|
||||
|
||||
@Override protected void onActivityResult( int requestCode, int resultCode, Intent data ){
|
||||
log.d( "onActivityResult" );
|
||||
|
@ -212,6 +256,7 @@ public class ActMain extends AppCompatActivity
|
|||
if( order != null && isOrderChanged( order ) ){
|
||||
pager_adapter.setOrder( pager, order );
|
||||
app_state.saveColumnList();
|
||||
updateColumnStrip();
|
||||
}
|
||||
|
||||
if( pager_adapter.column_list.isEmpty() ){
|
||||
|
@ -220,6 +265,7 @@ public class ActMain extends AppCompatActivity
|
|||
int select = data.getIntExtra( ActColumnList.EXTRA_SELECTION, - 1 );
|
||||
if( select != - 1 ){
|
||||
pager.setCurrentItem( select, true );
|
||||
scrollColumnStrip( select );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -245,6 +291,16 @@ public class ActMain extends AppCompatActivity
|
|||
posted_acct = data.getStringExtra( ActPost.EXTRA_POSTED_ACCT );
|
||||
posted_status_id = data.getLongExtra( ActPost.EXTRA_POSTED_STATUS_ID, 0L );
|
||||
}
|
||||
}else if( requestCode == REQUEST_COLUMN_COLOR ){
|
||||
if( data != null ){
|
||||
app_state.saveColumnList();
|
||||
int idx = data.getIntExtra( ActColumnCustomize.EXTRA_COLUMN_INDEX, 0 );
|
||||
ColumnViewHolder vh = pager_adapter.getColumnViewHolder( idx );
|
||||
if( vh != null ){
|
||||
vh.showColumnColor();
|
||||
}
|
||||
updateColumnStrip();
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onActivityResult( requestCode, resultCode, data );
|
||||
|
@ -419,16 +475,21 @@ public class ActMain extends AppCompatActivity
|
|||
ViewPager pager;
|
||||
ColumnPagerAdapter pager_adapter;
|
||||
View llEmpty;
|
||||
DrawerLayout drawer;
|
||||
LinearLayout llColumnStrip;
|
||||
HorizontalScrollView svColumnStrip;
|
||||
|
||||
void initUI(){
|
||||
setContentView( R.layout.act_main );
|
||||
|
||||
llEmpty = findViewById( R.id.llEmpty );
|
||||
|
||||
// // toolbar
|
||||
// Toolbar toolbar = (Toolbar) findViewById( R.id.toolbar );
|
||||
// setSupportActionBar( toolbar );
|
||||
|
||||
// navigation drawer
|
||||
final DrawerLayout drawer = (DrawerLayout) findViewById( R.id.drawer_layout );
|
||||
drawer = (DrawerLayout) findViewById( R.id.drawer_layout );
|
||||
// ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
|
||||
// this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close );
|
||||
// drawer.addDrawerListener( toggle );
|
||||
|
@ -437,30 +498,109 @@ public class ActMain extends AppCompatActivity
|
|||
NavigationView navigationView = (NavigationView) findViewById( R.id.nav_view );
|
||||
navigationView.setNavigationItemSelectedListener( this );
|
||||
|
||||
// floating action button
|
||||
View fabToot = (View) findViewById( R.id.fabToot );
|
||||
fabToot.setOnClickListener( new View.OnClickListener() {
|
||||
@Override public void onClick( View view ){
|
||||
performTootButton();
|
||||
}
|
||||
} );
|
||||
// floating action button
|
||||
View fabMenu = findViewById( R.id.fabMenu );
|
||||
fabMenu.setOnClickListener( new View.OnClickListener() {
|
||||
@Override public void onClick( View view ){
|
||||
if( ! drawer.isDrawerOpen( Gravity.START ) ){
|
||||
drawer.openDrawer( Gravity.START );
|
||||
}
|
||||
}
|
||||
} );
|
||||
View v;
|
||||
|
||||
v = findViewById( R.id.btnToot );
|
||||
v.setOnClickListener( this );
|
||||
|
||||
v = findViewById( R.id.btnMenu );
|
||||
v.setOnClickListener( this );
|
||||
|
||||
llColumnStrip = (LinearLayout) findViewById( R.id.llColumnStrip );
|
||||
|
||||
svColumnStrip = (HorizontalScrollView) findViewById( R.id.svColumnStrip );
|
||||
svColumnStrip.setHorizontalFadingEdgeEnabled( true );
|
||||
|
||||
// ViewPager
|
||||
pager = (ViewPager) findViewById( R.id.viewPager );
|
||||
pager_adapter = new ColumnPagerAdapter( this );
|
||||
pager.setAdapter( pager_adapter );
|
||||
pager.addOnPageChangeListener( this );
|
||||
|
||||
}
|
||||
|
||||
void updateColumnStrip(){
|
||||
llColumnStrip.removeAllViews();
|
||||
for( int i = 0, ie = app_state.column_list.size() ; i < ie ; ++ i ){
|
||||
|
||||
final Column column = app_state.column_list.get( i );
|
||||
|
||||
View viewRoot = getLayoutInflater().inflate( R.layout.lv_column_strip, llColumnStrip, false );
|
||||
ImageView ivIcon = (ImageView) viewRoot.findViewById( R.id.ivIcon );
|
||||
|
||||
viewRoot.setTag( i );
|
||||
viewRoot.setOnClickListener( new View.OnClickListener() {
|
||||
@Override public void onClick( View v ){
|
||||
onClickColumnStrip( (Integer) v.getTag() );
|
||||
}
|
||||
} );
|
||||
viewRoot.setContentDescription( column.getColumnName( true ) );
|
||||
//
|
||||
|
||||
int c = column.header_bg_color;
|
||||
if( c == 0 ){
|
||||
viewRoot.setBackgroundResource( R.drawable.btn_bg_ddd );
|
||||
}else{
|
||||
ViewCompat.setBackground( viewRoot,Styler.getAdaptiveRippleDrawable(
|
||||
c,
|
||||
(column.header_fg_color != 0 ? column.header_fg_color :
|
||||
Styler.getAttributeColor( this,R.attr.colorRippleEffect ))
|
||||
|
||||
) );
|
||||
}
|
||||
|
||||
c = column.header_fg_color;
|
||||
if( c == 0 ){
|
||||
Styler.setIconDefaultColor( this, ivIcon, Column.getIconAttrId( column.column_type ) );
|
||||
}else{
|
||||
Styler.setIconCustomColor( this, ivIcon, c, Column.getIconAttrId( column.column_type ) );
|
||||
}
|
||||
|
||||
//
|
||||
AcctColor ac = AcctColor.load( column.access_info.acct );
|
||||
if( AcctColor.hasColorForeground( ac ) ){
|
||||
View vAcctColor = viewRoot.findViewById( R.id.vAcctColor );
|
||||
vAcctColor.setBackgroundColor( ac.color_fg );
|
||||
}
|
||||
//
|
||||
llColumnStrip.addView( viewRoot );
|
||||
//
|
||||
|
||||
}
|
||||
svColumnStrip.requestLayout();
|
||||
}
|
||||
|
||||
private void scrollColumnStrip( final int select ){
|
||||
int child_count = llColumnStrip.getChildCount();
|
||||
if( select < 0 || select >= child_count ){
|
||||
return;
|
||||
}
|
||||
|
||||
View icon = llColumnStrip.getChildAt( select );
|
||||
|
||||
int sv_width = ( (View) llColumnStrip.getParent() ).getWidth();
|
||||
int ll_width = llColumnStrip.getWidth();
|
||||
int icon_width = icon.getWidth();
|
||||
int icon_left = icon.getLeft();
|
||||
|
||||
if( sv_width == 0 || ll_width == 0 || icon_width == 0 ){
|
||||
handler.postDelayed( new Runnable() {
|
||||
@Override public void run(){
|
||||
scrollColumnStrip( select );
|
||||
}
|
||||
}, 20L );
|
||||
|
||||
}
|
||||
|
||||
int sx = icon_left + icon_width / 2 - sv_width / 2;
|
||||
svColumnStrip.smoothScrollTo( sx, 0 );
|
||||
|
||||
}
|
||||
|
||||
private void onClickColumnStrip( int idx ){
|
||||
pager.setCurrentItem( idx, true );
|
||||
}
|
||||
|
||||
public void performAccountAdd(){
|
||||
LoginForm.showLoginForm( this, null, new LoginForm.LoginFormCallback() {
|
||||
@Override
|
||||
|
@ -520,14 +660,14 @@ public class ActMain extends AppCompatActivity
|
|||
Utils.showToast( ActMain.this, true, sv );
|
||||
log.e( result.error );
|
||||
}else{
|
||||
SavedAccount a = addPseudoAccount(instance);
|
||||
SavedAccount a = addPseudoAccount( instance );
|
||||
if( a != null ){
|
||||
// 疑似アカウントが追加された
|
||||
Utils.showToast( ActMain.this, false, R.string.server_confirmed );
|
||||
addColumn( a, Column.TYPE_LOCAL );
|
||||
dialog.dismiss();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -540,13 +680,13 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
} );
|
||||
progress.show();
|
||||
AsyncTaskCompat.executeParallel( task );
|
||||
task.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
SavedAccount addPseudoAccount(String host){
|
||||
SavedAccount addPseudoAccount( String host ){
|
||||
try{
|
||||
String username = "?";
|
||||
String full_acct = username + "@" + host;
|
||||
|
@ -557,8 +697,8 @@ public class ActMain extends AppCompatActivity
|
|||
|
||||
long row_id = SavedAccount.insert( host, full_acct, account_info, new JSONObject() );
|
||||
SavedAccount account = SavedAccount.loadAccount( log, row_id );
|
||||
if( account == null){
|
||||
throw new RuntimeException( "loadAccount returns null.");
|
||||
if( account == null ){
|
||||
throw new RuntimeException( "loadAccount returns null." );
|
||||
}
|
||||
account.notification_follow = false;
|
||||
account.notification_favourite = false;
|
||||
|
@ -568,8 +708,8 @@ public class ActMain extends AppCompatActivity
|
|||
return account;
|
||||
}catch( JSONException ex ){
|
||||
ex.printStackTrace();
|
||||
log.e(ex,"addPseudoAccount failed.");
|
||||
Utils.showToast( this, ex,"addPseudoAccount failed.");
|
||||
log.e( ex, "addPseudoAccount failed." );
|
||||
Utils.showToast( this, ex, "addPseudoAccount failed." );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -598,35 +738,35 @@ public class ActMain extends AppCompatActivity
|
|||
// https://mastodon.juggler.jp/@SubwayTooter
|
||||
final String host = m.group( 1 );
|
||||
final String user = Uri.decode( m.group( 2 ) );
|
||||
ArrayList<SavedAccount> account_list = SavedAccount.loadAccountList( log );
|
||||
ArrayList<SavedAccount> account_list_same_host = new ArrayList<>( );
|
||||
ArrayList< SavedAccount > account_list = SavedAccount.loadAccountList( log );
|
||||
ArrayList< SavedAccount > account_list_same_host = new ArrayList<>();
|
||||
|
||||
for( SavedAccount a : account_list){
|
||||
for( SavedAccount a : account_list ){
|
||||
if( host.equalsIgnoreCase( a.host ) ){
|
||||
account_list_same_host.add(a);
|
||||
account_list_same_host.add( a );
|
||||
}
|
||||
}
|
||||
|
||||
if( account_list_same_host.isEmpty() ){
|
||||
account_list_same_host.add( addPseudoAccount( host ));
|
||||
account_list_same_host.add( addPseudoAccount( host ) );
|
||||
}
|
||||
|
||||
AccountPicker.pick( this, true, true
|
||||
,getString(R.string.account_picker_open_user_who,user+"@"+host)
|
||||
,account_list_same_host
|
||||
, getString( R.string.account_picker_open_user_who, user + "@" + host )
|
||||
, account_list_same_host
|
||||
, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( final SavedAccount ai ){
|
||||
startGetAccount( ai, host, user, new GetAccountCallback() {
|
||||
@Override public void onGetAccount( TootAccount who ){
|
||||
if( who != null ){
|
||||
performOpenUser( ai, who );
|
||||
return;
|
||||
@Override public void onAccountPicked( final SavedAccount ai ){
|
||||
startGetAccount( ai, host, user, new GetAccountCallback() {
|
||||
@Override public void onGetAccount( TootAccount who ){
|
||||
if( who != null ){
|
||||
performOpenUser( ai, who );
|
||||
return;
|
||||
}
|
||||
openChromeTab( ai, uri.toString(), true );
|
||||
}
|
||||
openChromeTab( ai, uri.toString(), true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
}
|
||||
} );
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
@ -800,7 +940,7 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
} );
|
||||
progress.show();
|
||||
AsyncTaskCompat.executeParallel( task );
|
||||
task.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
void reloadAccountSetting(){
|
||||
|
@ -849,10 +989,12 @@ public class ActMain extends AppCompatActivity
|
|||
int page_delete = pager_adapter.column_list.indexOf( column );
|
||||
pager_adapter.removeColumn( pager, column );
|
||||
app_state.saveColumnList();
|
||||
updateColumnStrip();
|
||||
if( pager_adapter.getCount() == 0 ){
|
||||
llEmpty.setVisibility( View.VISIBLE );
|
||||
}else if( page_showing > 0 && page_showing == page_delete ){
|
||||
pager.setCurrentItem( page_showing - 1, true );
|
||||
scrollColumnStrip( page_showing - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -870,9 +1012,10 @@ public class ActMain extends AppCompatActivity
|
|||
//
|
||||
llEmpty.setVisibility( View.GONE );
|
||||
//
|
||||
Column col = new Column( app_state , ai, type, params );
|
||||
Column col = new Column( app_state, ai, type, params );
|
||||
int idx = pager_adapter.addColumn( pager, col );
|
||||
app_state.saveColumnList();
|
||||
updateColumnStrip();
|
||||
pager.setCurrentItem( idx, true );
|
||||
return col;
|
||||
}
|
||||
|
@ -887,13 +1030,13 @@ public class ActMain extends AppCompatActivity
|
|||
|
||||
public void performOpenUserFromAnotherAccount( final TootAccount who, ArrayList< SavedAccount > account_list_non_pseudo_same_instance ){
|
||||
AccountPicker.pick( this, false, false
|
||||
,getString(R.string.account_picker_open_user_who,AcctColor.getNickname( who.acct) )
|
||||
, getString( R.string.account_picker_open_user_who, AcctColor.getNickname( who.acct ) )
|
||||
, account_list_non_pseudo_same_instance
|
||||
, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
addColumn( ai, Column.TYPE_PROFILE, who.id );
|
||||
}
|
||||
} );
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
addColumn( ai, Column.TYPE_PROFILE, who.id );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public void performConversation( SavedAccount access_info, TootStatus status ){
|
||||
|
@ -902,20 +1045,20 @@ public class ActMain extends AppCompatActivity
|
|||
|
||||
private void performAddTimeline( boolean bAllowPseudo, final int type, final Object... args ){
|
||||
AccountPicker.pick( this, bAllowPseudo, true
|
||||
,getString(R.string.account_picker_add_timeline_of,Column.getColumnTypeName(this,type))
|
||||
, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
switch( type ){
|
||||
default:
|
||||
addColumn( ai, type, args );
|
||||
break;
|
||||
|
||||
case Column.TYPE_PROFILE:
|
||||
addColumn( ai, type, ai.id );
|
||||
break;
|
||||
, getString( R.string.account_picker_add_timeline_of, Column.getColumnTypeName( this, type ) )
|
||||
, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
switch( type ){
|
||||
default:
|
||||
addColumn( ai, type, args );
|
||||
break;
|
||||
|
||||
case Column.TYPE_PROFILE:
|
||||
addColumn( ai, type, ai.id );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
public void openHashTag( SavedAccount access_info, String tag ){
|
||||
|
@ -1004,7 +1147,7 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
} );
|
||||
progress.show();
|
||||
AsyncTaskCompat.executeParallel( task );
|
||||
task.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
static final Pattern reHashTag = Pattern.compile( "\\Ahttps://([^/]+)/tags/([^?#]+)\\z" );
|
||||
|
@ -1075,7 +1218,7 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
|
||||
// 他インスタンスのハッシュタグの表示
|
||||
private void openHashTagOtherInstance( final SavedAccount access_info, final String url, String host, final String tag ){
|
||||
private void openHashTagOtherInstance( final SavedAccount access_info, final String url, final String host, final String tag ){
|
||||
|
||||
ActionsDialog dialog = new ActionsDialog();
|
||||
|
||||
|
@ -1097,7 +1240,13 @@ public class ActMain extends AppCompatActivity
|
|||
} );
|
||||
|
||||
// 各アカウントで開く選択肢
|
||||
boolean has_host = false;
|
||||
for( SavedAccount a : account_list ){
|
||||
|
||||
if( host.equalsIgnoreCase( a.host ) ){
|
||||
has_host = true;
|
||||
}
|
||||
|
||||
final SavedAccount _a = a;
|
||||
dialog.addAction( getString( R.string.open_in_account, a.acct ), new Runnable() {
|
||||
@Override public void run(){
|
||||
|
@ -1106,7 +1255,16 @@ public class ActMain extends AppCompatActivity
|
|||
} );
|
||||
}
|
||||
|
||||
// TODO: もしカラならログイン無しアカウントで開きたいかも
|
||||
if( ! has_host ){
|
||||
dialog.addAction( getString( R.string.open_in_pseudo_account, "?@" + host ), new Runnable() {
|
||||
@Override public void run(){
|
||||
SavedAccount sa = addPseudoAccount( host );
|
||||
if( sa != null ){
|
||||
openHashTag( sa, tag );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
dialog.show( this, "#" + tag );
|
||||
|
||||
|
@ -1140,12 +1298,12 @@ public class ActMain extends AppCompatActivity
|
|||
public void performMentionFromAnotherAccount( SavedAccount access_info, final TootAccount who, ArrayList< SavedAccount > account_list_non_pseudo ){
|
||||
final String initial_text = "@" + access_info.getFullAcct( who ) + " ";
|
||||
AccountPicker.pick( this, false, false
|
||||
,getString(R.string.account_picker_toot )
|
||||
, getString( R.string.account_picker_toot )
|
||||
, account_list_non_pseudo, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
ActPost.open( ActMain.this, REQUEST_CODE_POST, ai.db_id, initial_text );
|
||||
}
|
||||
} );
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
ActPost.open( ActMain.this, REQUEST_CODE_POST, ai.db_id, initial_text );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1161,7 +1319,6 @@ public class ActMain extends AppCompatActivity
|
|||
/////////////////////////////////////////////////////////////////////////
|
||||
// favourite
|
||||
|
||||
|
||||
public void performFavourite( final SavedAccount account, final TootStatus status, final RelationChangedCallback callback ){
|
||||
//
|
||||
final String busy_key = account.host + ":" + status.id;
|
||||
|
@ -1255,14 +1412,14 @@ public class ActMain extends AppCompatActivity
|
|||
showColumnMatchAccount( account );
|
||||
}
|
||||
|
||||
}.execute();
|
||||
}.executeOnExecutor( App1.task_executor );
|
||||
// ファボ表示を更新中にする
|
||||
showColumnMatchAccount( account );
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// boost
|
||||
|
||||
|
||||
public void performBoost( final SavedAccount access_info, final TootStatus status, boolean bConfirmed, final RelationChangedCallback callback ){
|
||||
//
|
||||
final String busy_key = access_info.host + ":" + status.id;
|
||||
|
@ -1375,7 +1532,7 @@ public class ActMain extends AppCompatActivity
|
|||
showColumnMatchAccount( access_info );
|
||||
}
|
||||
|
||||
}.execute();
|
||||
}.executeOnExecutor( App1.task_executor );
|
||||
|
||||
showColumnMatchAccount( access_info );
|
||||
}
|
||||
|
@ -1384,12 +1541,12 @@ public class ActMain extends AppCompatActivity
|
|||
|
||||
private void performAccountSetting(){
|
||||
AccountPicker.pick( this, true, true
|
||||
,getString(R.string.account_picker_open_setting)
|
||||
, getString( R.string.account_picker_open_setting )
|
||||
, new AccountPicker.AccountPickerCallback() {
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
ActAccountSetting.open( ActMain.this, ai, REQUEST_CODE_ACCOUNT_SETTING );
|
||||
}
|
||||
} );
|
||||
@Override public void onAccountPicked( SavedAccount ai ){
|
||||
ActAccountSetting.open( ActMain.this, ai, REQUEST_CODE_ACCOUNT_SETTING );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
private void performAppSetting(){
|
||||
|
@ -1400,7 +1557,7 @@ public class ActMain extends AppCompatActivity
|
|||
// column list
|
||||
|
||||
private void openColumnList(){
|
||||
ActColumnList.open(this,pager.getCurrentItem(),REQUEST_CODE_COLUMN_LIST);
|
||||
ActColumnList.open( this, pager.getCurrentItem(), REQUEST_CODE_COLUMN_LIST );
|
||||
}
|
||||
|
||||
// private void dumpColumnList(){
|
||||
|
@ -1410,8 +1567,6 @@ public class ActMain extends AppCompatActivity
|
|||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
interface RelationChangedCallback {
|
||||
|
@ -1624,7 +1779,7 @@ public class ActMain extends AppCompatActivity
|
|||
Utils.showToast( ActMain.this, false, result.error );
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
// acct で指定したユーザをリモートフォローする
|
||||
|
@ -1743,7 +1898,7 @@ public class ActMain extends AppCompatActivity
|
|||
Utils.showToast( ActMain.this, false, result.error );
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
@ -1814,7 +1969,7 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
|
||||
}.execute();
|
||||
}.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
void callBlock( final SavedAccount access_info, final TootAccount who, final boolean bBlock, final RelationChangedCallback callback ){
|
||||
|
@ -1881,7 +2036,7 @@ public class ActMain extends AppCompatActivity
|
|||
Utils.showToast( ActMain.this, false, result.error );
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
void callFollowRequestAuthorize( final SavedAccount access_info
|
||||
|
@ -1932,7 +2087,7 @@ public class ActMain extends AppCompatActivity
|
|||
Utils.showToast( ActMain.this, false, result.error );
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
void deleteStatus( final SavedAccount access_info, final long status_id ){
|
||||
|
@ -1977,7 +2132,7 @@ public class ActMain extends AppCompatActivity
|
|||
Utils.showToast( ActMain.this, false, result.error );
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
interface ReportCompleteCallback {
|
||||
|
@ -2034,7 +2189,7 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
|
||||
}.execute();
|
||||
}.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
void openReportForm( @NonNull final SavedAccount account, @NonNull final TootAccount who, @NonNull final TootStatus status ){
|
||||
|
@ -2193,7 +2348,7 @@ public class ActMain extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
|
||||
}.execute();
|
||||
}.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,10 +11,6 @@ import android.content.SharedPreferences;
|
|||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
|
@ -26,7 +22,6 @@ import android.support.annotation.NonNull;
|
|||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.os.AsyncTaskCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
|
@ -41,7 +36,6 @@ import android.widget.ImageButton;
|
|||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
@ -55,7 +49,6 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
import it.sephiroth.android.library.exif2.ExifInterface;
|
||||
import jp.juggler.subwaytooter.api.TootApiClient;
|
||||
import jp.juggler.subwaytooter.api.TootApiResult;
|
||||
import jp.juggler.subwaytooter.api.entity.TootAttachment;
|
||||
|
@ -316,6 +309,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
if( sent_intent != null ){
|
||||
String action = sent_intent.getAction();
|
||||
String type = sent_intent.getType();
|
||||
//noinspection StatementWithEmptyBody
|
||||
if( type == null ){
|
||||
//
|
||||
}else if( type.startsWith( "image/" ) ){
|
||||
|
@ -781,7 +775,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
iv.setVisibility( View.GONE );
|
||||
}else{
|
||||
iv.setVisibility( View.VISIBLE );
|
||||
iv.setCornerRadius( pref,16f );
|
||||
iv.setCornerRadius( pref, 16f );
|
||||
PostAttachment a = attachment_list.get( idx );
|
||||
if( a.attachment != null && a.status == PostAttachment.ATTACHMENT_UPLOADED ){
|
||||
iv.setImageUrl( a.attachment.preview_url, App1.getImageLoader() );
|
||||
|
@ -870,175 +864,12 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
break;
|
||||
}
|
||||
|
||||
// EXIF回転情報の取得
|
||||
Integer orientation;
|
||||
|
||||
InputStream is = getContentResolver().openInputStream( uri );
|
||||
if( is == null ){
|
||||
Utils.showToast( this, false, "could not open image." );
|
||||
break;
|
||||
}
|
||||
try{
|
||||
ExifInterface exif = new ExifInterface();
|
||||
exif.readExif( is, ExifInterface.Options.OPTION_IFD_0 | ExifInterface.Options.OPTION_IFD_1 | ExifInterface.Options.OPTION_IFD_EXIF );
|
||||
orientation = exif.getTagIntValue( ExifInterface.TAG_ORIENTATION );
|
||||
}finally{
|
||||
IOUtils.closeQuietly( is );
|
||||
}
|
||||
|
||||
// 画像のサイズを調べる
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
options.inScaled = false;
|
||||
is = getContentResolver().openInputStream( uri );
|
||||
if( is == null ){
|
||||
Utils.showToast( this, false, "could not open image." );
|
||||
break;
|
||||
}
|
||||
try{
|
||||
BitmapFactory.decodeStream( is, null, options );
|
||||
}finally{
|
||||
IOUtils.closeQuietly( is );
|
||||
}
|
||||
int src_width = options.outWidth;
|
||||
int src_height = options.outHeight;
|
||||
if( src_width <= 0 || src_height <= 0 ){
|
||||
Utils.showToast( this, false, "could not get image bounds." );
|
||||
break;
|
||||
}
|
||||
|
||||
// 長辺
|
||||
int size = ( src_width > src_height ? src_width : src_height );
|
||||
|
||||
// 設定からリサイズ指定を読む
|
||||
int resize_to = list_resize_max[ pref.getInt( Pref.KEY_RESIZE_IMAGE, 4 ) ];
|
||||
|
||||
// リサイズも回転も必要がない場合
|
||||
if( ( orientation == null || orientation == 1 )
|
||||
&& ( resize_to <= 0 || size <= resize_to )
|
||||
){
|
||||
log.d( "createOpener: no need to resize & rotate" );
|
||||
break;
|
||||
}
|
||||
|
||||
//noinspection StatementWithEmptyBody
|
||||
if( size > resize_to ){
|
||||
// 縮小が必要
|
||||
}else{
|
||||
// 縮小は不要
|
||||
resize_to = size;
|
||||
}
|
||||
|
||||
// inSampleSizeを計算
|
||||
int bits = 0;
|
||||
int x = size;
|
||||
while( x > resize_to * 2 ){
|
||||
++ bits;
|
||||
x >>= 1;
|
||||
}
|
||||
options.inJustDecodeBounds = false;
|
||||
options.inSampleSize = 1 << bits;
|
||||
is = getContentResolver().openInputStream( uri );
|
||||
if( is == null ){
|
||||
Utils.showToast( this, false, "could not open image." );
|
||||
break;
|
||||
}
|
||||
Bitmap src;
|
||||
try{
|
||||
src = BitmapFactory.decodeStream( is, null, options );
|
||||
}finally{
|
||||
IOUtils.closeQuietly( is );
|
||||
}
|
||||
if( src == null ){
|
||||
Utils.showToast( this, false, "could not decode image." );
|
||||
break;
|
||||
}
|
||||
try{
|
||||
src_width = options.outWidth;
|
||||
src_height = options.outHeight;
|
||||
float scale;
|
||||
int dst_width;
|
||||
int dst_height;
|
||||
if( src_width >= src_height ){
|
||||
scale = resize_to / (float) src_width;
|
||||
dst_width = resize_to;
|
||||
dst_height = (int) ( 0.5f + src_height / (float) src_width * resize_to );
|
||||
if( dst_height < 1 ) dst_height = 1;
|
||||
}else{
|
||||
scale = resize_to / (float) src_height;
|
||||
dst_height = resize_to;
|
||||
dst_width = (int) ( 0.5f + src_width / (float) src_height * resize_to );
|
||||
if( dst_width < 1 ) dst_width = 1;
|
||||
}
|
||||
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.reset();
|
||||
|
||||
// 画像の中心が原点に来るようにして
|
||||
matrix.postTranslate( src_width * - 0.5f, src_height * - 0.5f );
|
||||
// スケーリング
|
||||
matrix.postScale( scale, scale );
|
||||
// 回転情報があれば回転
|
||||
if( orientation != null ){
|
||||
int tmp;
|
||||
switch( orientation.shortValue() ){
|
||||
default:
|
||||
break;
|
||||
case 2:
|
||||
matrix.postScale( 1f, - 1f );
|
||||
break; // 上下反転
|
||||
case 3:
|
||||
matrix.postRotate( 180f );
|
||||
break; // 180度回転
|
||||
case 4:
|
||||
matrix.postScale( - 1f, 1f );
|
||||
break; // 左右反転
|
||||
case 5:
|
||||
tmp = dst_width;
|
||||
//noinspection SuspiciousNameCombination
|
||||
dst_width = dst_height;
|
||||
dst_height = tmp;
|
||||
matrix.postScale( 1f, - 1f );
|
||||
matrix.postRotate( - 90f );
|
||||
break;
|
||||
case 6:
|
||||
tmp = dst_width;
|
||||
//noinspection SuspiciousNameCombination
|
||||
dst_width = dst_height;
|
||||
dst_height = tmp;
|
||||
matrix.postRotate( 90f );
|
||||
break;
|
||||
case 7:
|
||||
tmp = dst_width;
|
||||
//noinspection SuspiciousNameCombination
|
||||
dst_width = dst_height;
|
||||
dst_height = tmp;
|
||||
matrix.postScale( 1f, - 1f );
|
||||
matrix.postRotate( 90f );
|
||||
break;
|
||||
case 8:
|
||||
tmp = dst_width;
|
||||
//noinspection SuspiciousNameCombination
|
||||
dst_width = dst_height;
|
||||
dst_height = tmp;
|
||||
matrix.postRotate( - 90f );
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 表示領域に埋まるように平行移動
|
||||
matrix.postTranslate( dst_width * 0.5f, dst_height * 0.5f );
|
||||
|
||||
// 出力用Bitmap作成
|
||||
Bitmap dst = Bitmap.createBitmap( dst_width, dst_height, Bitmap.Config.ARGB_8888 );
|
||||
if( dst == null ){
|
||||
Utils.showToast( this, false, "bitmap creation failed." );
|
||||
break;
|
||||
}
|
||||
Bitmap bitmap = Utils.createResizedBitmap( log, this, uri, true,resize_to );
|
||||
if( bitmap != null ){
|
||||
try{
|
||||
Canvas canvas = new Canvas( dst );
|
||||
Paint paint = new Paint();
|
||||
paint.setFilterBitmap( true );
|
||||
canvas.drawBitmap( src, matrix, paint );
|
||||
File cache_dir = getExternalCacheDir();
|
||||
if( cache_dir == null ){
|
||||
Utils.showToast( this, false, "getExternalCacheDir returns null." );
|
||||
|
@ -1052,15 +883,15 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
FileOutputStream os = new FileOutputStream( temp_file );
|
||||
try{
|
||||
if( is_jpeg ){
|
||||
dst.compress( Bitmap.CompressFormat.JPEG, 95, os );
|
||||
bitmap.compress( Bitmap.CompressFormat.JPEG, 95, os );
|
||||
}else{
|
||||
dst.compress( Bitmap.CompressFormat.PNG, 100, os );
|
||||
bitmap.compress( Bitmap.CompressFormat.PNG, 100, os );
|
||||
}
|
||||
}finally{
|
||||
os.close();
|
||||
}
|
||||
log.d( "createOpener: resized to %sx%s", dst_width, dst_height );
|
||||
return new InputStreamOpener() {
|
||||
|
||||
return new ActPost.InputStreamOpener() {
|
||||
@Override public InputStream open() throws IOException{
|
||||
return new FileInputStream( temp_file );
|
||||
}
|
||||
|
@ -1075,10 +906,8 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
}
|
||||
};
|
||||
}finally{
|
||||
dst.recycle();
|
||||
bitmap.recycle();
|
||||
}
|
||||
}finally{
|
||||
src.recycle();
|
||||
}
|
||||
|
||||
}catch( Throwable ex ){
|
||||
|
@ -1224,7 +1053,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
pa.callback.onPostAttachmentComplete( pa );
|
||||
}
|
||||
|
||||
}.execute();
|
||||
}.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
// 添付メディア投稿が完了したら呼ばれる
|
||||
|
@ -1564,7 +1393,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
}
|
||||
} );
|
||||
progress.show();
|
||||
AsyncTaskCompat.executeParallel( task );
|
||||
task.executeOnExecutor( App1.task_executor );
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
@ -1579,7 +1408,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
}else{
|
||||
llReply.setVisibility( View.VISIBLE );
|
||||
tvReplyTo.setText( HTMLDecoder.decodeHTML( account, in_reply_to_text ) );
|
||||
ivReply.setCornerRadius( pref,16f );
|
||||
ivReply.setCornerRadius( pref, 16f );
|
||||
ivReply.setImageUrl( in_reply_to_image, App1.getImageLoader() );
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.database.sqlite.SQLiteDatabase;
|
|||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Typeface;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.util.LruCache;
|
||||
import android.widget.ImageView;
|
||||
|
||||
|
@ -19,7 +20,13 @@ import com.android.volley.toolbox.ImageLoader;
|
|||
import com.android.volley.toolbox.Volley;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import jp.juggler.subwaytooter.table.AcctColor;
|
||||
import jp.juggler.subwaytooter.table.AcctSet;
|
||||
|
@ -212,6 +219,13 @@ public class App1 extends Application {
|
|||
|
||||
public static SharedPreferences pref;
|
||||
|
||||
|
||||
/**
|
||||
* An {@link Executor} that can be used to execute tasks in parallel.
|
||||
*/
|
||||
public static ThreadPoolExecutor task_executor;
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(){
|
||||
super.onCreate();
|
||||
|
@ -221,6 +235,40 @@ public class App1 extends Application {
|
|||
.build()
|
||||
);
|
||||
|
||||
if( task_executor == null ){
|
||||
|
||||
// We want at least 2 threads and at most 4 threads in the core pool,
|
||||
// preferring to have 1 less than the CPU count to avoid saturating
|
||||
// the CPU with background work
|
||||
|
||||
int CPU_COUNT = Runtime.getRuntime().availableProcessors();
|
||||
int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
|
||||
int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
|
||||
int KEEP_ALIVE_SECONDS = 30;
|
||||
|
||||
// デフォルトだとキューはmax128で、溢れることがある
|
||||
BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<>(999);
|
||||
|
||||
ThreadFactory sThreadFactory = new ThreadFactory() {
|
||||
private final AtomicInteger mCount = new AtomicInteger(1);
|
||||
public Thread newThread( @NonNull Runnable r) {
|
||||
return new Thread(r, "SubwayTooterTask #" + mCount.getAndIncrement());
|
||||
}
|
||||
};
|
||||
|
||||
task_executor = new ThreadPoolExecutor(
|
||||
CORE_POOL_SIZE // pool size
|
||||
, MAXIMUM_POOL_SIZE // max pool size
|
||||
, KEEP_ALIVE_SECONDS // keep-alive-seconds
|
||||
, TimeUnit.SECONDS // unit of keep-alive-seconds
|
||||
, sPoolWorkQueue
|
||||
, sThreadFactory
|
||||
);
|
||||
|
||||
task_executor.allowCoreThreadTimeOut(true);
|
||||
}
|
||||
|
||||
|
||||
if( pref == null ){
|
||||
pref = Pref.pref( getApplicationContext() );
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.net.Uri;
|
|||
import android.os.AsyncTask;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.os.AsyncTaskCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
|
@ -94,7 +93,11 @@ class Column {
|
|||
private static final String KEY_DONT_SHOW_REPLY = "dont_show_reply";
|
||||
private static final String KEY_REGEX_TEXT = "regex_text";
|
||||
|
||||
// static final java.lang.String KEY_COLUMN_COLOR = "color";
|
||||
static final String KEY_HEADER_BACKGROUND_COLOR = "header_background_color";
|
||||
static final String KEY_HEADER_TEXT_COLOR = "header_text_color";
|
||||
static final String KEY_COLUMN_BACKGROUND_COLOR = "column_background_color";
|
||||
static final String KEY_COLUMN_BACKGROUND_IMAGE = "column_background_image";
|
||||
static final String KEY_COLUMN_BACKGROUND_IMAGE_ALPHA = "column_background_image_alpha";
|
||||
|
||||
private static final String KEY_PROFILE_ID = "profile_id";
|
||||
private static final String KEY_PROFILE_TAB = "tab";
|
||||
|
@ -138,6 +141,12 @@ class Column {
|
|||
boolean dont_show_reply;
|
||||
String regex_text;
|
||||
|
||||
int header_bg_color;
|
||||
int header_fg_color;
|
||||
int column_bg_color;
|
||||
String column_bg_image;
|
||||
float column_bg_image_alpha = 1f;
|
||||
|
||||
private long profile_id;
|
||||
volatile TootAccount who_account;
|
||||
int profile_tab = TAB_STATUS;
|
||||
|
@ -193,6 +202,13 @@ class Column {
|
|||
item.put( KEY_DONT_SHOW_REPLY, dont_show_reply );
|
||||
item.put( KEY_REGEX_TEXT, regex_text );
|
||||
|
||||
|
||||
item.put( KEY_HEADER_BACKGROUND_COLOR, header_bg_color );
|
||||
item.put( KEY_HEADER_TEXT_COLOR, header_fg_color );
|
||||
item.put( KEY_COLUMN_BACKGROUND_COLOR, column_bg_color );
|
||||
item.put( KEY_COLUMN_BACKGROUND_IMAGE, column_bg_image );
|
||||
item.put( KEY_COLUMN_BACKGROUND_IMAGE_ALPHA, (double) column_bg_image_alpha );
|
||||
|
||||
switch( column_type ){
|
||||
case TYPE_CONVERSATION:
|
||||
case TYPE_BOOSTED_BY:
|
||||
|
@ -235,6 +251,12 @@ class Column {
|
|||
this.dont_show_reply = src.optBoolean( KEY_DONT_SHOW_REPLY );
|
||||
this.regex_text = Utils.optStringX( src, KEY_REGEX_TEXT );
|
||||
|
||||
this.header_bg_color = src.optInt( KEY_HEADER_BACKGROUND_COLOR );
|
||||
this.header_fg_color = src.optInt( KEY_HEADER_TEXT_COLOR );
|
||||
this.column_bg_color = src.optInt( KEY_COLUMN_BACKGROUND_COLOR );
|
||||
this.column_bg_image = Utils.optStringX( src, KEY_COLUMN_BACKGROUND_IMAGE );
|
||||
this.column_bg_image_alpha = (float)src.optDouble( KEY_COLUMN_BACKGROUND_IMAGE_ALPHA ,1.0f);
|
||||
|
||||
switch( column_type ){
|
||||
|
||||
case TYPE_CONVERSATION:
|
||||
|
@ -446,19 +468,14 @@ class Column {
|
|||
|
||||
boolean bSimpleList;
|
||||
|
||||
boolean bFirstInitialized = false;
|
||||
|
||||
|
||||
private void init(){
|
||||
|
||||
|
||||
bSimpleList = ( column_type != Column.TYPE_CONVERSATION && app_state.pref.getBoolean( Pref.KEY_SIMPLE_LIST, false ) );
|
||||
|
||||
|
||||
|
||||
startLoading();
|
||||
}
|
||||
|
||||
void onNicknameUpdated(){
|
||||
|
||||
fireShowColumnHeader();
|
||||
}
|
||||
|
||||
|
@ -820,6 +837,7 @@ class Column {
|
|||
void startLoading(){
|
||||
cancelLastTask();
|
||||
|
||||
bFirstInitialized = true;
|
||||
list_data.clear();
|
||||
mRefreshLoadingError = null;
|
||||
bRefreshLoading = false;
|
||||
|
@ -1107,7 +1125,7 @@ class Column {
|
|||
}
|
||||
};
|
||||
|
||||
AsyncTaskCompat.executeParallel( task );
|
||||
task.executeOnExecutor(App1.task_executor);
|
||||
}
|
||||
|
||||
private static final Pattern reMaxId = Pattern.compile( "&max_id=(\\d+)" ); // より古いデータの取得に使う
|
||||
|
@ -1831,7 +1849,7 @@ class Column {
|
|||
}
|
||||
};
|
||||
|
||||
AsyncTaskCompat.executeParallel( task );
|
||||
task.executeOnExecutor(App1.task_executor);
|
||||
|
||||
}
|
||||
|
||||
|
@ -2238,7 +2256,7 @@ class Column {
|
|||
}
|
||||
};
|
||||
|
||||
AsyncTaskCompat.executeParallel( task );
|
||||
task.executeOnExecutor(App1.task_executor);
|
||||
}
|
||||
|
||||
private static final int heightSpec = View.MeasureSpec.makeMeasureSpec( 0, View.MeasureSpec.UNSPECIFIED );
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package jp.juggler.subwaytooter;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.text.Editable;
|
||||
|
@ -12,6 +16,7 @@ import android.widget.Button;
|
|||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -37,12 +42,12 @@ class ColumnViewHolder
|
|||
final ActMain activity;
|
||||
final Column column;
|
||||
final AtomicBoolean is_destroyed = new AtomicBoolean( false );
|
||||
final ItemListAdapter status_adapter;
|
||||
private final ItemListAdapter status_adapter;
|
||||
|
||||
ColumnViewHolder( ActMain activity, Column column ){
|
||||
this.activity = activity;
|
||||
this.column = column;
|
||||
this.status_adapter = new ItemListAdapter( activity,column );
|
||||
this.status_adapter = new ItemListAdapter( activity, column );
|
||||
}
|
||||
|
||||
private boolean isPageDestroyed(){
|
||||
|
@ -50,11 +55,16 @@ class ColumnViewHolder
|
|||
}
|
||||
|
||||
void onPageDestroy( @SuppressWarnings("UnusedParameters") View root ){
|
||||
saveScrollPosition();
|
||||
log.d( "onPageDestroy:%s", column.getColumnName( true ) );
|
||||
|
||||
saveScrollPosition();
|
||||
|
||||
column.setColumnViewHolder( null );
|
||||
|
||||
closeBitmaps();
|
||||
|
||||
activity.closeListItemPopup();
|
||||
|
||||
}
|
||||
|
||||
private TextView tvLoading;
|
||||
|
@ -69,24 +79,42 @@ class ColumnViewHolder
|
|||
private View llColumnSetting;
|
||||
private EditText etRegexFilter;
|
||||
private TextView tvRegexFilterError;
|
||||
private View btnColumnClose;
|
||||
private ImageView ivColumnIcon;
|
||||
|
||||
private View llColumnHeader;
|
||||
private TextView tvColumnIndex;
|
||||
private ImageButton btnColumnSetting;
|
||||
private ImageButton btnColumnReload;
|
||||
private ImageButton btnColumnClose;
|
||||
|
||||
private View flColumnBackground;
|
||||
private ImageView ivColumnBackgroundImage;
|
||||
|
||||
void onPageCreate( View root, int page_idx, int page_count ){
|
||||
log.d( "onPageCreate:%s", column.getColumnName( true ) );
|
||||
|
||||
( (TextView) root.findViewById( R.id.tvColumnIndex ) )
|
||||
.setText( activity.getString( R.string.column_index, page_idx + 1, page_count ) );
|
||||
flColumnBackground = root.findViewById( R.id.flColumnBackground );
|
||||
ivColumnBackgroundImage = (ImageView) root.findViewById( R.id.ivColumnBackgroundImage );
|
||||
llColumnHeader = root.findViewById( R.id.llColumnHeader );
|
||||
|
||||
tvColumnIndex = (TextView) root.findViewById( R.id.tvColumnIndex );
|
||||
tvColumnIndex.setText( activity.getString( R.string.column_index, page_idx + 1, page_count ) );
|
||||
|
||||
tvColumnName = (TextView) root.findViewById( R.id.tvColumnName );
|
||||
tvColumnContext = (TextView) root.findViewById( R.id.tvColumnContext );
|
||||
ivColumnIcon = (ImageView) root.findViewById( R.id.ivColumnIcon );
|
||||
btnColumnClose = root.findViewById( R.id.btnColumnClose );
|
||||
|
||||
btnColumnSetting = (ImageButton) root.findViewById( R.id.btnColumnSetting );
|
||||
btnColumnReload = (ImageButton) root.findViewById( R.id.btnColumnReload );
|
||||
btnColumnClose = (ImageButton) root.findViewById( R.id.btnColumnClose );
|
||||
|
||||
btnColumnSetting.setOnClickListener( this );
|
||||
btnColumnReload.setOnClickListener( this );
|
||||
btnColumnClose.setOnClickListener( this );
|
||||
|
||||
root.findViewById( R.id.btnColumnReload ).setOnClickListener( this );
|
||||
root.findViewById( R.id.llColumnHeader ).setOnClickListener( this );
|
||||
llColumnHeader.setOnClickListener( this );
|
||||
|
||||
root.findViewById( R.id.btnColor ).setOnClickListener( this );
|
||||
|
||||
tvLoading = (TextView) root.findViewById( R.id.tvLoading );
|
||||
listView = (MyListView) root.findViewById( R.id.listView );
|
||||
|
@ -130,10 +158,7 @@ class ColumnViewHolder
|
|||
break;
|
||||
}
|
||||
|
||||
View btnColumnSetting = root.findViewById( R.id.btnColumnSetting );
|
||||
llColumnSetting = root.findViewById( R.id.llColumnSetting );
|
||||
btnColumnSetting.setVisibility( View.VISIBLE );
|
||||
btnColumnSetting.setOnClickListener( this );
|
||||
llColumnSetting.setVisibility( View.GONE );
|
||||
|
||||
CheckBox cb;
|
||||
|
@ -214,7 +239,7 @@ class ColumnViewHolder
|
|||
}
|
||||
|
||||
if( column.column_type == Column.TYPE_PROFILE ){
|
||||
vh_header = new HeaderViewHolder( activity,column, listView );
|
||||
vh_header = new HeaderViewHolder( activity, column, listView );
|
||||
listView.addHeaderView( vh_header.viewRoot );
|
||||
}
|
||||
|
||||
|
@ -231,9 +256,103 @@ class ColumnViewHolder
|
|||
//
|
||||
|
||||
column.setColumnViewHolder( this );
|
||||
|
||||
showColumnColor();
|
||||
|
||||
showContent();
|
||||
}
|
||||
|
||||
void showColumnColor(){
|
||||
int c = column.header_bg_color;
|
||||
if( c == 0 ){
|
||||
llColumnHeader.setBackgroundResource( R.drawable.btn_bg_ddd );
|
||||
}else{
|
||||
ViewCompat.setBackground( llColumnHeader,Styler.getAdaptiveRippleDrawable(
|
||||
c,
|
||||
(column.header_fg_color != 0 ? column.header_fg_color :
|
||||
Styler.getAttributeColor( activity,R.attr.colorRippleEffect ))
|
||||
) );
|
||||
}
|
||||
|
||||
c = column.header_fg_color;
|
||||
if( c == 0 ){
|
||||
tvColumnIndex.setTextColor( Styler.getAttributeColor( activity, R.attr.colorColumnHeaderPageNumber ) );
|
||||
tvColumnName.setTextColor( Styler.getAttributeColor( activity, android.R.attr.textColorPrimary ) );
|
||||
Styler.setIconDefaultColor( activity, ivColumnIcon, Column.getIconAttrId( column.column_type ) );
|
||||
Styler.setIconDefaultColor( activity, btnColumnSetting, R.attr.ic_tune );
|
||||
Styler.setIconDefaultColor( activity, btnColumnReload, R.attr.btn_refresh );
|
||||
Styler.setIconDefaultColor( activity, btnColumnClose, R.attr.btn_close );
|
||||
}else{
|
||||
tvColumnIndex.setTextColor( c );
|
||||
tvColumnName.setTextColor( c );
|
||||
Styler.setIconCustomColor( activity, ivColumnIcon, c, Column.getIconAttrId( column.column_type ) );
|
||||
Styler.setIconCustomColor( activity, btnColumnSetting, c, R.attr.ic_tune );
|
||||
Styler.setIconCustomColor( activity, btnColumnReload, c, R.attr.btn_refresh );
|
||||
Styler.setIconCustomColor( activity, btnColumnClose, c, R.attr.btn_close );
|
||||
}
|
||||
|
||||
c = column.column_bg_color;
|
||||
if( c == 0 ){
|
||||
ViewCompat.setBackground( flColumnBackground, null );
|
||||
}else{
|
||||
flColumnBackground.setBackgroundColor( c );
|
||||
}
|
||||
|
||||
ivColumnBackgroundImage.setAlpha( column.column_bg_image_alpha );
|
||||
|
||||
loadBackgroundImage( ivColumnBackgroundImage, column.column_bg_image );
|
||||
|
||||
}
|
||||
|
||||
private String last_image_uri;
|
||||
private Bitmap last_image_bitmap;
|
||||
|
||||
private void closeBitmaps(){
|
||||
try{
|
||||
if( last_image_bitmap != null ){
|
||||
ivColumnBackgroundImage.setVisibility( View.GONE );
|
||||
ivColumnBackgroundImage.setImageDrawable( null );
|
||||
last_image_uri = null;
|
||||
last_image_bitmap.recycle();
|
||||
last_image_bitmap = null;
|
||||
}
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void loadBackgroundImage( ImageView iv, String url ){
|
||||
try{
|
||||
if( TextUtils.isEmpty( url ) ){
|
||||
closeBitmaps();
|
||||
return;
|
||||
}else if( url.equals( last_image_uri ) ){
|
||||
// 今表示してるのと同じ
|
||||
return;
|
||||
}
|
||||
|
||||
// 直前のBitmapを掃除する
|
||||
closeBitmaps();
|
||||
|
||||
iv.setVisibility( View.VISIBLE );
|
||||
|
||||
int w = iv.getResources().getDisplayMetrics().widthPixels;
|
||||
int h = iv.getResources().getDisplayMetrics().heightPixels;
|
||||
int resize_max = ( w > h ? w : h );
|
||||
|
||||
Uri uri = Uri.parse( url );
|
||||
last_image_bitmap = Utils.createResizedBitmap( log, activity, uri, false, resize_max );
|
||||
if( last_image_bitmap != null ){
|
||||
iv.setImageBitmap( last_image_bitmap );
|
||||
last_image_uri = url;
|
||||
}
|
||||
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable proc_start_filter = new Runnable() {
|
||||
@Override public void run(){
|
||||
if( isPageDestroyed() ) return;
|
||||
|
@ -274,7 +393,7 @@ class ColumnViewHolder
|
|||
}
|
||||
|
||||
@Override public void onRefresh( SwipyRefreshLayoutDirection direction ){
|
||||
column.startRefresh( false, direction == SwipyRefreshLayoutDirection.BOTTOM ,-1L,-1);
|
||||
column.startRefresh( false, direction == SwipyRefreshLayoutDirection.BOTTOM, - 1L, - 1 );
|
||||
}
|
||||
|
||||
@Override public void onCheckedChanged( CompoundButton view, boolean isChecked ){
|
||||
|
@ -342,6 +461,11 @@ class ColumnViewHolder
|
|||
case R.id.btnDeleteNotification:
|
||||
activity.deleteNotification( false, column.access_info );
|
||||
break;
|
||||
|
||||
case R.id.btnColor:
|
||||
int idx = activity.app_state.column_list.indexOf( column );
|
||||
ActColumnCustomize.open( activity, idx, ActMain.REQUEST_COLUMN_COLOR );
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -403,8 +527,6 @@ class ColumnViewHolder
|
|||
|
||||
showColumnCloseButton();
|
||||
|
||||
ivColumnIcon.setImageResource( Styler.getAttributeResourceId( activity, Column.getIconAttrId( column.column_type ) ) );
|
||||
|
||||
}
|
||||
|
||||
void showContent(){
|
||||
|
@ -420,6 +542,11 @@ class ColumnViewHolder
|
|||
vh_header.bind( column.who_account );
|
||||
}
|
||||
|
||||
if( ! column.bFirstInitialized ){
|
||||
showError( "initializing" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( column.bInitialLoading ){
|
||||
String message = column.task_progress;
|
||||
if( message == null ) message = "loading?";
|
||||
|
@ -466,7 +593,7 @@ class ColumnViewHolder
|
|||
if( listView.getVisibility() == View.VISIBLE ){
|
||||
column.scroll_save = new ScrollPosition( listView );
|
||||
}else{
|
||||
column.scroll_save = new ScrollPosition( 0,0 );
|
||||
column.scroll_save = new ScrollPosition( 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
//package jp.juggler.subwaytooter;
|
||||
//
|
||||
//import android.os.AsyncTask;
|
||||
//import android.os.SystemClock;
|
||||
//import android.support.annotation.NonNull;
|
||||
//
|
||||
//import java.util.HashMap;
|
||||
//
|
||||
//import jp.juggler.subwaytooter.api.TootApiClient;
|
||||
//import jp.juggler.subwaytooter.api.TootApiResult;
|
||||
//import jp.juggler.subwaytooter.api.entity.TootRelationShip;
|
||||
//import jp.juggler.subwaytooter.table.SavedAccount;
|
||||
//import jp.juggler.subwaytooter.util.LogCategory;
|
||||
//
|
||||
//class RelationshipMap {
|
||||
//
|
||||
// private static final LogCategory log = new LogCategory( "RelationshipMap" );
|
||||
//
|
||||
//
|
||||
// interface UpdateCallback {
|
||||
// void onRelationShipUpdate();
|
||||
// }
|
||||
//
|
||||
// private static class RelationshipPerAccount extends HashMap< Long, TootRelationShip > {
|
||||
// long last_update;
|
||||
// }
|
||||
//
|
||||
// private final HashMap< String, RelationshipPerAccount > map_account = new HashMap<>();
|
||||
//
|
||||
// @NonNull
|
||||
// private RelationshipPerAccount getRelationshipPerAccount( @NonNull SavedAccount access_info ){
|
||||
// RelationshipPerAccount ra;
|
||||
// ra = map_account.get( access_info.acct );
|
||||
// if( ra == null ){
|
||||
// ra = new RelationshipPerAccount();
|
||||
// map_account.put( access_info.acct, ra );
|
||||
// }
|
||||
// return ra;
|
||||
// }
|
||||
//
|
||||
// public TootRelationShip get( @NonNull SavedAccount access_info, long id ){
|
||||
// return getRelationshipPerAccount( access_info ).get( id );
|
||||
// }
|
||||
//
|
||||
// public void put( @NonNull SavedAccount access_info, @NonNull TootRelationShip relation ){
|
||||
// getRelationshipPerAccount( access_info ).put( relation.id,relation );
|
||||
// }
|
||||
//
|
||||
// public void addFollowing( SavedAccount access_info, long id ){
|
||||
// RelationshipPerAccount ra = getRelationshipPerAccount( access_info );
|
||||
// TootRelationShip rs = ra.get( id);
|
||||
// if(rs == null ){
|
||||
// rs = new TootRelationShip();
|
||||
// ra.put( id, rs );
|
||||
// }
|
||||
// rs.following = true;
|
||||
// }
|
||||
//
|
||||
// void checkUpdate( @NonNull final ActMain activity, @NonNull final SavedAccount access_info, final UpdateCallback callback ){
|
||||
// final RelationshipPerAccount ra = getRelationshipPerAccount( access_info );
|
||||
// long now = SystemClock.elapsedRealtime();
|
||||
// if( now - ra.last_update < 300000L ) return;
|
||||
// ra.last_update = now;
|
||||
//
|
||||
// new AsyncTask< Void, Void, TootApiResult >() {
|
||||
//
|
||||
// TootRelationShip.List list;
|
||||
//
|
||||
// @Override protected TootApiResult doInBackground( Void... params ){
|
||||
//
|
||||
// TootApiClient client = new TootApiClient( activity, new TootApiClient.Callback() {
|
||||
// @Override public boolean isApiCancelled(){
|
||||
// return isCancelled();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void publishApiProgress( final String s ){
|
||||
// }
|
||||
// } );
|
||||
//
|
||||
// client.setAccount( access_info );
|
||||
// TootApiResult result = client.request( "/api/v1/accounts/relationships" );
|
||||
// if( result != null && result.array != null ){
|
||||
// list = TootRelationShip.parseList( log, result.array );
|
||||
// }
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onCancelled( TootApiResult result ){
|
||||
// onPostExecute( null );
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onPostExecute( TootApiResult result ){
|
||||
//
|
||||
// if( isCancelled() || result == null ){
|
||||
// return;
|
||||
// }
|
||||
// if( list != null ){
|
||||
// for( TootRelationShip item : list ){
|
||||
// ra.put( item.id, item );
|
||||
// }
|
||||
// callback.onRelationShipUpdate();
|
||||
// }
|
||||
// }
|
||||
// }.execute();
|
||||
// }
|
||||
//}
|
|
@ -1,16 +1,25 @@
|
|||
package jp.juggler.subwaytooter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.RippleDrawable;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.graphics.drawable.shapes.RectShape;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import jp.juggler.subwaytooter.api.entity.TootStatus;
|
||||
|
@ -120,4 +129,50 @@ public class Styler {
|
|||
|
||||
|
||||
}
|
||||
|
||||
static void setIconDefaultColor( Context context,ImageView iv, int icon_attr ){
|
||||
iv.setImageResource( Styler.getAttributeResourceId( context, icon_attr ) );
|
||||
}
|
||||
|
||||
static void setIconCustomColor( Context context,ImageView iv, int color,int icon_attr ){
|
||||
Drawable d = Styler.getAttributeDrawable( context,icon_attr ).mutate();
|
||||
d.setColorFilter( color, PorterDuff.Mode.SRC_ATOP );
|
||||
iv.setImageDrawable( d );
|
||||
}
|
||||
|
||||
|
||||
static Drawable getAdaptiveRippleDrawable( int normalColor, int pressedColor){
|
||||
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
return new RippleDrawable(
|
||||
ColorStateList.valueOf(pressedColor)
|
||||
,getShape(normalColor)
|
||||
, null
|
||||
);
|
||||
} else {
|
||||
return getStateListDrawable(normalColor, pressedColor);
|
||||
}
|
||||
}
|
||||
|
||||
private static Drawable getShape(int color) {
|
||||
RectShape r = new RectShape();
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(r);
|
||||
shapeDrawable.getPaint().setColor(color);
|
||||
return shapeDrawable;
|
||||
}
|
||||
|
||||
|
||||
private static StateListDrawable getStateListDrawable( int normalColor, int pressedColor) {
|
||||
StateListDrawable states = new StateListDrawable();
|
||||
states.addState(new int[]{android.R.attr.state_pressed},
|
||||
new ColorDrawable(pressedColor));
|
||||
states.addState(new int[]{android.R.attr.state_focused},
|
||||
new ColorDrawable(pressedColor));
|
||||
states.addState(new int[]{android.R.attr.state_activated},
|
||||
new ColorDrawable(pressedColor));
|
||||
states.addState(new int[]{},
|
||||
new ColorDrawable(normalColor));
|
||||
return states;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.widget.ImageView;
|
|||
import android.widget.TextView;
|
||||
|
||||
import jp.juggler.subwaytooter.ActMain;
|
||||
import jp.juggler.subwaytooter.App1;
|
||||
import jp.juggler.subwaytooter.R;
|
||||
import jp.juggler.subwaytooter.util.Utils;
|
||||
|
||||
|
@ -59,7 +60,7 @@ public class DlgQRCode {
|
|||
} );
|
||||
progress.show();
|
||||
|
||||
AsyncTaskCompat.executeParallel( task );
|
||||
task.executeOnExecutor( App1.task_executor);
|
||||
}
|
||||
|
||||
public static void open( @NonNull final ActMain activity ,final CharSequence message,final String url ){
|
||||
|
|
|
@ -2,12 +2,15 @@ package jp.juggler.subwaytooter.util;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
@ -18,6 +21,11 @@ import java.util.Locale;
|
|||
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
|
@ -38,6 +46,7 @@ import android.view.inputmethod.InputMethodManager;
|
|||
import android.webkit.MimeTypeMap;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.w3c.dom.Element;
|
||||
|
@ -50,7 +59,9 @@ import java.util.Map;
|
|||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import it.sephiroth.android.library.exif2.ExifInterface;
|
||||
import jp.juggler.subwaytooter.ActMain;
|
||||
import jp.juggler.subwaytooter.ActPost;
|
||||
|
||||
public class Utils {
|
||||
|
||||
|
@ -87,49 +98,49 @@ public class Utils {
|
|||
|
||||
public static String formatBytes( long t ){
|
||||
return bytes_format.format( t );
|
||||
|
||||
// StringBuilder sb = new StringBuilder();
|
||||
// long n;
|
||||
// // giga
|
||||
// n = t / 1000000000L;
|
||||
// if( n > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%dg", n ) );
|
||||
// t -= n * 1000000000L;
|
||||
// }
|
||||
// // Mega
|
||||
// n = t / 1000000L;
|
||||
// if( sb.length() > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%03dm", n ) );
|
||||
// t -= n * 1000000L;
|
||||
// }else if( n > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%dm", n ) );
|
||||
// t -= n * 1000000L;
|
||||
// }
|
||||
// // kilo
|
||||
// n = t / 1000L;
|
||||
// if( sb.length() > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%03dk", n ) );
|
||||
// t -= n * 1000L;
|
||||
// }else if( n > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%dk", n ) );
|
||||
// t -= n * 1000L;
|
||||
// }
|
||||
// // remain
|
||||
// if( sb.length() > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%03d", t ) );
|
||||
// }else if( n > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%d", t ) );
|
||||
// }
|
||||
//
|
||||
// return sb.toString();
|
||||
|
||||
// StringBuilder sb = new StringBuilder();
|
||||
// long n;
|
||||
// // giga
|
||||
// n = t / 1000000000L;
|
||||
// if( n > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%dg", n ) );
|
||||
// t -= n * 1000000000L;
|
||||
// }
|
||||
// // Mega
|
||||
// n = t / 1000000L;
|
||||
// if( sb.length() > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%03dm", n ) );
|
||||
// t -= n * 1000000L;
|
||||
// }else if( n > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%dm", n ) );
|
||||
// t -= n * 1000000L;
|
||||
// }
|
||||
// // kilo
|
||||
// n = t / 1000L;
|
||||
// if( sb.length() > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%03dk", n ) );
|
||||
// t -= n * 1000L;
|
||||
// }else if( n > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%dk", n ) );
|
||||
// t -= n * 1000L;
|
||||
// }
|
||||
// // remain
|
||||
// if( sb.length() > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%03d", t ) );
|
||||
// }else if( n > 0 ){
|
||||
// sb.append( String.format( Locale.JAPAN, "%d", t ) );
|
||||
// }
|
||||
//
|
||||
// return sb.toString();
|
||||
}
|
||||
|
||||
// public static PendingIntent createAlarmPendingIntent( Context context ){
|
||||
// Intent i = new Intent( context.getApplicationContext(), Receiver1.class );
|
||||
// i.setAction( Receiver1.ACTION_ALARM );
|
||||
// return PendingIntent.getBroadcast( context.getApplicationContext(), 0, i, 0 );
|
||||
// }
|
||||
//
|
||||
// Intent i = new Intent( context.getApplicationContext(), Receiver1.class );
|
||||
// i.setAction( Receiver1.ACTION_ALARM );
|
||||
// return PendingIntent.getBroadcast( context.getApplicationContext(), 0, i, 0 );
|
||||
// }
|
||||
//
|
||||
// 文字列とバイト列の変換
|
||||
@NonNull public static byte[] encodeUTF8( @NonNull String str ){
|
||||
try{
|
||||
|
@ -164,7 +175,7 @@ public class Utils {
|
|||
public static String optStringX( JSONArray src, int key ){
|
||||
return src.isNull( key ) ? null : src.optString( key );
|
||||
}
|
||||
|
||||
|
||||
public static ArrayList< String > parseStringArray( LogCategory log, JSONArray array ){
|
||||
ArrayList< String > dst_list = new ArrayList<>();
|
||||
if( array != null ){
|
||||
|
@ -279,15 +290,15 @@ public class Utils {
|
|||
if( url == null ) return null;
|
||||
return encodeBase64Safe( encodeSHA256( encodeUTF8( url ) ) );
|
||||
}
|
||||
|
||||
// public static String name2url(String entry) {
|
||||
// if(entry==null) return null;
|
||||
// byte[] b = new byte[entry.length()/2];
|
||||
// for(int i=0,ie=b.length;i<ie;++i){
|
||||
// b[i]= (byte)((hex2int(entry.charAt(i*2))<<4)| hex2int(entry.charAt(i*2+1)));
|
||||
// }
|
||||
// return decodeUTF8(b);
|
||||
// }
|
||||
|
||||
// public static String name2url(String entry) {
|
||||
// if(entry==null) return null;
|
||||
// byte[] b = new byte[entry.length()/2];
|
||||
// for(int i=0,ie=b.length;i<ie;++i){
|
||||
// b[i]= (byte)((hex2int(entry.charAt(i*2))<<4)| hex2int(entry.charAt(i*2+1)));
|
||||
// }
|
||||
// return decodeUTF8(b);
|
||||
// }
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
|
@ -424,7 +435,7 @@ public class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
public static void hideKeyboard(Context context,View v ){
|
||||
public static void hideKeyboard( Context context, View v ){
|
||||
InputMethodManager imm = (InputMethodManager) context.getSystemService( Context.INPUT_METHOD_SERVICE );
|
||||
imm.hideSoftInputFromWindow( v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS );
|
||||
}
|
||||
|
@ -432,99 +443,99 @@ public class Utils {
|
|||
public static String ellipsize( String t, int max ){
|
||||
return ( t.length() > max ? t.substring( 0, max - 1 ) + "…" : t );
|
||||
}
|
||||
|
||||
// public static int getEnumStringId( String residPrefix, String name,Context context ) {
|
||||
// name = residPrefix + name;
|
||||
// try{
|
||||
// int iv = context.getResources().getIdentifier(name,"string",context.getPackageName() );
|
||||
// if( iv != 0 ) return iv;
|
||||
// }catch(Throwable ex){
|
||||
// }
|
||||
// log.e("missing resid for %s",name);
|
||||
// return R.string.Dialog_Cancel;
|
||||
// }
|
||||
|
||||
// public static String getConnectionResultErrorMessage( ConnectionResult connectionResult ){
|
||||
// int code = connectionResult.getErrorCode();
|
||||
// String msg = connectionResult.getErrorMessage();
|
||||
// if( TextUtils.isEmpty( msg ) ){
|
||||
// switch( code ){
|
||||
// case ConnectionResult.SUCCESS:
|
||||
// msg = "SUCCESS";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_MISSING:
|
||||
// msg = "SERVICE_MISSING";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
|
||||
// msg = "SERVICE_VERSION_UPDATE_REQUIRED";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_DISABLED:
|
||||
// msg = "SERVICE_DISABLED";
|
||||
// break;
|
||||
// case ConnectionResult.SIGN_IN_REQUIRED:
|
||||
// msg = "SIGN_IN_REQUIRED";
|
||||
// break;
|
||||
// case ConnectionResult.INVALID_ACCOUNT:
|
||||
// msg = "INVALID_ACCOUNT";
|
||||
// break;
|
||||
// case ConnectionResult.RESOLUTION_REQUIRED:
|
||||
// msg = "RESOLUTION_REQUIRED";
|
||||
// break;
|
||||
// case ConnectionResult.NETWORK_ERROR:
|
||||
// msg = "NETWORK_ERROR";
|
||||
// break;
|
||||
// case ConnectionResult.INTERNAL_ERROR:
|
||||
// msg = "INTERNAL_ERROR";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_INVALID:
|
||||
// msg = "SERVICE_INVALID";
|
||||
// break;
|
||||
// case ConnectionResult.DEVELOPER_ERROR:
|
||||
// msg = "DEVELOPER_ERROR";
|
||||
// break;
|
||||
// case ConnectionResult.LICENSE_CHECK_FAILED:
|
||||
// msg = "LICENSE_CHECK_FAILED";
|
||||
// break;
|
||||
// case ConnectionResult.CANCELED:
|
||||
// msg = "CANCELED";
|
||||
// break;
|
||||
// case ConnectionResult.TIMEOUT:
|
||||
// msg = "TIMEOUT";
|
||||
// break;
|
||||
// case ConnectionResult.INTERRUPTED:
|
||||
// msg = "INTERRUPTED";
|
||||
// break;
|
||||
// case ConnectionResult.API_UNAVAILABLE:
|
||||
// msg = "API_UNAVAILABLE";
|
||||
// break;
|
||||
// case ConnectionResult.SIGN_IN_FAILED:
|
||||
// msg = "SIGN_IN_FAILED";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_UPDATING:
|
||||
// msg = "SERVICE_UPDATING";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_MISSING_PERMISSION:
|
||||
// msg = "SERVICE_MISSING_PERMISSION";
|
||||
// break;
|
||||
// case ConnectionResult.RESTRICTED_PROFILE:
|
||||
// msg = "RESTRICTED_PROFILE";
|
||||
// break;
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// return msg;
|
||||
// }
|
||||
|
||||
// public static String getConnectionSuspendedMessage( int i ){
|
||||
// switch( i ){
|
||||
// default:
|
||||
// return "?";
|
||||
// case GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST:
|
||||
// return "NETWORK_LOST";
|
||||
// case GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED:
|
||||
// return "SERVICE_DISCONNECTED";
|
||||
// }
|
||||
// }
|
||||
|
||||
// public static int getEnumStringId( String residPrefix, String name,Context context ) {
|
||||
// name = residPrefix + name;
|
||||
// try{
|
||||
// int iv = context.getResources().getIdentifier(name,"string",context.getPackageName() );
|
||||
// if( iv != 0 ) return iv;
|
||||
// }catch(Throwable ex){
|
||||
// }
|
||||
// log.e("missing resid for %s",name);
|
||||
// return R.string.Dialog_Cancel;
|
||||
// }
|
||||
|
||||
// public static String getConnectionResultErrorMessage( ConnectionResult connectionResult ){
|
||||
// int code = connectionResult.getErrorCode();
|
||||
// String msg = connectionResult.getErrorMessage();
|
||||
// if( TextUtils.isEmpty( msg ) ){
|
||||
// switch( code ){
|
||||
// case ConnectionResult.SUCCESS:
|
||||
// msg = "SUCCESS";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_MISSING:
|
||||
// msg = "SERVICE_MISSING";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
|
||||
// msg = "SERVICE_VERSION_UPDATE_REQUIRED";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_DISABLED:
|
||||
// msg = "SERVICE_DISABLED";
|
||||
// break;
|
||||
// case ConnectionResult.SIGN_IN_REQUIRED:
|
||||
// msg = "SIGN_IN_REQUIRED";
|
||||
// break;
|
||||
// case ConnectionResult.INVALID_ACCOUNT:
|
||||
// msg = "INVALID_ACCOUNT";
|
||||
// break;
|
||||
// case ConnectionResult.RESOLUTION_REQUIRED:
|
||||
// msg = "RESOLUTION_REQUIRED";
|
||||
// break;
|
||||
// case ConnectionResult.NETWORK_ERROR:
|
||||
// msg = "NETWORK_ERROR";
|
||||
// break;
|
||||
// case ConnectionResult.INTERNAL_ERROR:
|
||||
// msg = "INTERNAL_ERROR";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_INVALID:
|
||||
// msg = "SERVICE_INVALID";
|
||||
// break;
|
||||
// case ConnectionResult.DEVELOPER_ERROR:
|
||||
// msg = "DEVELOPER_ERROR";
|
||||
// break;
|
||||
// case ConnectionResult.LICENSE_CHECK_FAILED:
|
||||
// msg = "LICENSE_CHECK_FAILED";
|
||||
// break;
|
||||
// case ConnectionResult.CANCELED:
|
||||
// msg = "CANCELED";
|
||||
// break;
|
||||
// case ConnectionResult.TIMEOUT:
|
||||
// msg = "TIMEOUT";
|
||||
// break;
|
||||
// case ConnectionResult.INTERRUPTED:
|
||||
// msg = "INTERRUPTED";
|
||||
// break;
|
||||
// case ConnectionResult.API_UNAVAILABLE:
|
||||
// msg = "API_UNAVAILABLE";
|
||||
// break;
|
||||
// case ConnectionResult.SIGN_IN_FAILED:
|
||||
// msg = "SIGN_IN_FAILED";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_UPDATING:
|
||||
// msg = "SERVICE_UPDATING";
|
||||
// break;
|
||||
// case ConnectionResult.SERVICE_MISSING_PERMISSION:
|
||||
// msg = "SERVICE_MISSING_PERMISSION";
|
||||
// break;
|
||||
// case ConnectionResult.RESTRICTED_PROFILE:
|
||||
// msg = "RESTRICTED_PROFILE";
|
||||
// break;
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// return msg;
|
||||
// }
|
||||
|
||||
// public static String getConnectionSuspendedMessage( int i ){
|
||||
// switch( i ){
|
||||
// default:
|
||||
// return "?";
|
||||
// case GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST:
|
||||
// return "NETWORK_LOST";
|
||||
// case GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED:
|
||||
// return "SERVICE_DISCONNECTED";
|
||||
// }
|
||||
// }
|
||||
|
||||
static HashMap< String, String > mime_type_ex = null;
|
||||
static final Object mime_type_ex_lock = new Object();
|
||||
|
@ -580,6 +591,193 @@ public class Utils {
|
|||
return sb;
|
||||
}
|
||||
|
||||
public static Bitmap createResizedBitmap( LogCategory log, Context context, Uri uri, boolean skipIfNoNeedToResizeAndRotate, int resize_to ){
|
||||
try{
|
||||
// EXIF回転情報の取得
|
||||
Integer orientation;
|
||||
|
||||
InputStream is = context.getContentResolver().openInputStream( uri );
|
||||
if( is == null ){
|
||||
Utils.showToast( context, false, "could not open image." );
|
||||
return null;
|
||||
}
|
||||
|
||||
try{
|
||||
ExifInterface exif = new ExifInterface();
|
||||
exif.readExif( is, ExifInterface.Options.OPTION_IFD_0 | ExifInterface.Options.OPTION_IFD_1 | ExifInterface.Options.OPTION_IFD_EXIF );
|
||||
orientation = exif.getTagIntValue( ExifInterface.TAG_ORIENTATION );
|
||||
}finally{
|
||||
IOUtils.closeQuietly( is );
|
||||
}
|
||||
|
||||
// 画像のサイズを調べる
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
options.inScaled = false;
|
||||
is = context.getContentResolver().openInputStream( uri );
|
||||
if( is == null ){
|
||||
Utils.showToast( context, false, "could not open image." );
|
||||
return null;
|
||||
}
|
||||
try{
|
||||
BitmapFactory.decodeStream( is, null, options );
|
||||
}finally{
|
||||
IOUtils.closeQuietly( is );
|
||||
}
|
||||
int src_width = options.outWidth;
|
||||
int src_height = options.outHeight;
|
||||
if( src_width <= 0 || src_height <= 0 ){
|
||||
Utils.showToast( context, false, "could not get image bounds." );
|
||||
return null;
|
||||
}
|
||||
|
||||
// 長辺
|
||||
int size = ( src_width > src_height ? src_width : src_height );
|
||||
|
||||
// リサイズも回転も必要がない場合
|
||||
if( skipIfNoNeedToResizeAndRotate
|
||||
&& ( orientation == null || orientation == 1 )
|
||||
&& ( resize_to <= 0 || size <= resize_to )
|
||||
|
||||
){
|
||||
log.d( "createOpener: no need to resize & rotate" );
|
||||
return null;
|
||||
}
|
||||
|
||||
//noinspection StatementWithEmptyBody
|
||||
if( size > resize_to ){
|
||||
// 縮小が必要
|
||||
}else{
|
||||
// 縮小は不要
|
||||
resize_to = size;
|
||||
}
|
||||
|
||||
// inSampleSizeを計算
|
||||
int bits = 0;
|
||||
int x = size;
|
||||
while( x > resize_to * 2 ){
|
||||
++ bits;
|
||||
x >>= 1;
|
||||
}
|
||||
options.inJustDecodeBounds = false;
|
||||
options.inSampleSize = 1 << bits;
|
||||
is = context.getContentResolver().openInputStream( uri );
|
||||
if( is == null ){
|
||||
Utils.showToast( context, false, "could not open image." );
|
||||
return null;
|
||||
}
|
||||
Bitmap src;
|
||||
try{
|
||||
src = BitmapFactory.decodeStream( is, null, options );
|
||||
}finally{
|
||||
IOUtils.closeQuietly( is );
|
||||
}
|
||||
if( src == null ){
|
||||
Utils.showToast( context, false, "could not decode image." );
|
||||
return null;
|
||||
}
|
||||
try{
|
||||
src_width = options.outWidth;
|
||||
src_height = options.outHeight;
|
||||
float scale;
|
||||
int dst_width;
|
||||
int dst_height;
|
||||
if( src_width >= src_height ){
|
||||
scale = resize_to / (float) src_width;
|
||||
dst_width = resize_to;
|
||||
dst_height = (int) ( 0.5f + src_height / (float) src_width * resize_to );
|
||||
if( dst_height < 1 ) dst_height = 1;
|
||||
}else{
|
||||
scale = resize_to / (float) src_height;
|
||||
dst_height = resize_to;
|
||||
dst_width = (int) ( 0.5f + src_width / (float) src_height * resize_to );
|
||||
if( dst_width < 1 ) dst_width = 1;
|
||||
}
|
||||
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.reset();
|
||||
|
||||
// 画像の中心が原点に来るようにして
|
||||
matrix.postTranslate( src_width * - 0.5f, src_height * - 0.5f );
|
||||
// スケーリング
|
||||
matrix.postScale( scale, scale );
|
||||
// 回転情報があれば回転
|
||||
if( orientation != null ){
|
||||
int tmp;
|
||||
switch( orientation.shortValue() ){
|
||||
default:
|
||||
break;
|
||||
case 2:
|
||||
matrix.postScale( 1f, - 1f );
|
||||
break; // 上下反転
|
||||
case 3:
|
||||
matrix.postRotate( 180f );
|
||||
break; // 180度回転
|
||||
case 4:
|
||||
matrix.postScale( - 1f, 1f );
|
||||
break; // 左右反転
|
||||
case 5:
|
||||
tmp = dst_width;
|
||||
//noinspection SuspiciousNameCombination
|
||||
dst_width = dst_height;
|
||||
dst_height = tmp;
|
||||
matrix.postScale( 1f, - 1f );
|
||||
matrix.postRotate( - 90f );
|
||||
break;
|
||||
case 6:
|
||||
tmp = dst_width;
|
||||
//noinspection SuspiciousNameCombination
|
||||
dst_width = dst_height;
|
||||
dst_height = tmp;
|
||||
matrix.postRotate( 90f );
|
||||
break;
|
||||
case 7:
|
||||
tmp = dst_width;
|
||||
//noinspection SuspiciousNameCombination
|
||||
dst_width = dst_height;
|
||||
dst_height = tmp;
|
||||
matrix.postScale( 1f, - 1f );
|
||||
matrix.postRotate( 90f );
|
||||
break;
|
||||
case 8:
|
||||
tmp = dst_width;
|
||||
//noinspection SuspiciousNameCombination
|
||||
dst_width = dst_height;
|
||||
dst_height = tmp;
|
||||
matrix.postRotate( - 90f );
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 表示領域に埋まるように平行移動
|
||||
matrix.postTranslate( dst_width * 0.5f, dst_height * 0.5f );
|
||||
|
||||
// 出力用Bitmap作成
|
||||
Bitmap dst = Bitmap.createBitmap( dst_width, dst_height, Bitmap.Config.ARGB_8888 );
|
||||
if( dst == null ){
|
||||
Utils.showToast( context, false, "bitmap creation failed." );
|
||||
return null;
|
||||
}
|
||||
try{
|
||||
Canvas canvas = new Canvas( dst );
|
||||
Paint paint = new Paint();
|
||||
paint.setFilterBitmap( true );
|
||||
canvas.drawBitmap( src, matrix, paint );
|
||||
log.d( "createResizedBitmap: resized to %sx%s", dst_width, dst_height );
|
||||
Bitmap tmp = dst;
|
||||
dst = null;
|
||||
return tmp;
|
||||
}finally{
|
||||
if( dst != null ) dst.recycle();
|
||||
}
|
||||
}finally{
|
||||
src.recycle();
|
||||
}
|
||||
}catch( Throwable ex ){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static class FileInfo {
|
||||
|
||||
Uri uri;
|
||||
|
@ -610,13 +808,13 @@ public class Utils {
|
|||
StorageManager sm = (StorageManager) context.getApplicationContext().getSystemService( Context.STORAGE_SERVICE );
|
||||
|
||||
// SDカードスロットのある7.0端末が手元にないから検証できない
|
||||
// if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ){
|
||||
// for(StorageVolume volume : sm.getStorageVolumes() ){
|
||||
// // String path = volume.getPath();
|
||||
// String state = volume.getState();
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ){
|
||||
// for(StorageVolume volume : sm.getStorageVolumes() ){
|
||||
// // String path = volume.getPath();
|
||||
// String state = volume.getState();
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
Method getVolumeList = sm.getClass().getMethod( "getVolumeList" );
|
||||
Object[] volumes = (Object[]) getVolumeList.invoke( sm );
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp"
|
||||
>
|
||||
|
||||
|
||||
<View style="@style/setting_divider"/>
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/column_header"
|
||||
/>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llColumnHeader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingBottom="3dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="3dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivColumnHeader"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:importantForAccessibility="no"
|
||||
tools:src="?attr/btn_federate_tl"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvColumnName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
tools:text="@string/federate_timeline"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/background_color"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnHeaderBackgroundEdit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/edit"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnHeaderBackgroundReset"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/reset"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/foreground_color"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnHeaderTextEdit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/edit"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnHeaderTextReset"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/reset"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View style="@style/setting_divider"/>
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/column_background"
|
||||
/>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/flColumnBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivColumnBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:importantForAccessibility="no"
|
||||
android:scaleType="centerCrop"
|
||||
/>
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/color"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnColumnBackgroundColor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/edit"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnColumnBackgroundColorReset"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/reset"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/image"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnColumnBackgroundImage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pick_image"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnColumnBackgroundImageReset"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/reset"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/image_alpha"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/sbColumnBackgroundAlpha"
|
||||
style="@style/setting_horizontal_stretch"
|
||||
android:layout_height="48dp"
|
||||
android:paddingEnd="32dp"
|
||||
android:paddingStart="32dp"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<View style="@style/setting_divider"/>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
|
@ -12,62 +12,120 @@
|
|||
tools:openDrawer="start"
|
||||
>
|
||||
|
||||
<FrameLayout
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llEmpty"
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
<LinearLayout
|
||||
android:id="@+id/llEmpty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="@string/column_empty"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="@string/column_empty"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<android.support.v4.view.ViewPager
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnMenu"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/btn_bg_ddd"
|
||||
app:srcCompat="?attr/ic_hamburger"
|
||||
android:contentDescription="@string/menu"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorImageButton"
|
||||
/>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:cacheColorHint="#00000000"
|
||||
android:fadingEdge="horizontal"
|
||||
android:fadingEdgeLength="20dp"
|
||||
android:fillViewport="true"
|
||||
android:scrollbars="none"
|
||||
android:background="?attr/colorColumnStripBackground"
|
||||
android:id="@+id/svColumnStrip"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llColumnStrip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
/>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorImageButton"
|
||||
/>
|
||||
<ImageButton
|
||||
android:id="@+id/btnToot"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/btn_bg_ddd"
|
||||
app:srcCompat="?attr/ic_edit"
|
||||
android:contentDescription="@string/toot"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<android.support.v4.view.ViewPager
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fabToot"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
app:srcCompat="?attr/ic_toot"
|
||||
/>
|
||||
<!--<android.support.design.widget.FloatingActionButton-->
|
||||
<!--android:id="@+id/"-->
|
||||
<!--android:layout_width="wrap_content"-->
|
||||
<!--android:layout_height="wrap_content"-->
|
||||
<!--android:layout_gravity="bottom|end"-->
|
||||
<!--android:layout_marginBottom="4dp"-->
|
||||
<!--android:layout_marginEnd="4dp"-->
|
||||
<!--app:srcCompat="?attr/ic_toot"-->
|
||||
<!--/>-->
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fabMenu"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|start"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
app:srcCompat="?attr/ic_menu"
|
||||
/>
|
||||
<!--<ImageButton-->
|
||||
<!--android:id="@+id/fabMenu"-->
|
||||
<!--android:layout_width="48dp"-->
|
||||
<!--android:layout_height="48dp"-->
|
||||
<!--android:layout_gravity="top|start"-->
|
||||
<!--android:background="@drawable/btn_bg_transparent"-->
|
||||
<!--app:srcCompat="?attr/ic_hamburger"-->
|
||||
<!--/>-->
|
||||
</FrameLayout>
|
||||
<!--<android.support.design.widget.FloatingActionButton-->
|
||||
<!--android:id="@+id/fabMenu"-->
|
||||
<!--android:layout_width="wrap_content"-->
|
||||
<!--android:layout_height="wrap_content"-->
|
||||
<!--android:layout_gravity="bottom|start"-->
|
||||
<!--android:layout_marginBottom="4dp"-->
|
||||
<!--android:layout_marginStart="4dp"-->
|
||||
<!--app:srcCompat="?attr/ic_menu"-->
|
||||
<!--/>-->
|
||||
|
||||
|
||||
<!--<android.support.design.widget.CoordinatorLayout-->
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
<TextView
|
||||
style="@style/setting_row_label"
|
||||
android:text="@string/nickname_label"
|
||||
android:labelFor="@+id/etNickname"
|
||||
/>
|
||||
|
||||
<LinearLayout style="@style/setting_row_form">
|
||||
|
@ -94,6 +95,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/edit"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<Button
|
||||
|
@ -101,6 +103,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/reset"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -119,6 +122,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/edit"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<Button
|
||||
|
@ -126,6 +130,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/reset"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -157,6 +162,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/save"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<Button
|
||||
|
@ -166,6 +172,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/discard"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/btn_bg_ddd"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivIcon"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
tools:ignore="ContentDescription"
|
||||
android:importantForAccessibility="no"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:id="@+id/vAcctColor"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="3dp"
|
||||
android:layout_marginTop="3dp"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
|
@ -64,6 +64,7 @@
|
|||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:id="@+id/ivColumnIcon"
|
||||
android:importantForAccessibility="no"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/tvColumnName"
|
||||
|
@ -192,6 +193,15 @@
|
|||
android:id="@+id/btnDeleteNotification"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/color_and_background"
|
||||
android:id="@+id/btnColor"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
|
@ -235,38 +245,49 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLoading"
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
/>
|
||||
android:id="@+id/flColumnBackground"
|
||||
>
|
||||
|
||||
<com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout
|
||||
android:id="@+id/swipyRefreshLayout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srl_direction="both">
|
||||
|
||||
<jp.juggler.subwaytooter.util.MyListView
|
||||
android:id="@+id/listView"
|
||||
<ImageView
|
||||
android:id="@+id/ivColumnBackgroundImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
|
||||
android:clipToPadding="false"
|
||||
android:fadeScrollbars="false"
|
||||
android:fastScrollEnabled="true"
|
||||
android:paddingBottom="64dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingStart="12dp"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
android:dividerHeight="1dp"
|
||||
android:divider="?attr/colorSettingDivider"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
|
||||
</com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout>
|
||||
<TextView
|
||||
android:id="@+id/tvLoading"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
/>
|
||||
|
||||
<com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout
|
||||
android:id="@+id/swipyRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:srl_direction="both">
|
||||
|
||||
<jp.juggler.subwaytooter.util.MyListView
|
||||
android:id="@+id/listView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
android:clipToPadding="false"
|
||||
android:fadeScrollbars="false"
|
||||
android:fastScrollEnabled="true"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingStart="12dp"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
android:dividerHeight="1dp"
|
||||
android:divider="?attr/colorSettingDivider"
|
||||
/>
|
||||
|
||||
</com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout>
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
|
@ -277,5 +277,14 @@
|
|||
<string name="toot">Toot</string>
|
||||
<string name="visibility">Visibility</string>
|
||||
<string name="dont_round_avatar">Don\'t round corner of avatar image (app restart required)</string>
|
||||
<string name="color_and_background">Color and Background…</string>
|
||||
<string name="column_background">column background</string>
|
||||
<string name="column_header">column header</string>
|
||||
<string name="foreground_color">foreground color</string>
|
||||
<string name="image">image</string>
|
||||
<string name="image_alpha">image alpha</string>
|
||||
<string name="menu">Menu</string>
|
||||
<string name="open_in_pseudo_account">open in pseudo account %1$s</string>
|
||||
<string name="pick_image">pick image</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -273,4 +273,13 @@
|
|||
<string name="toot">トゥート</string>
|
||||
<string name="visibility">公開範囲</string>
|
||||
<string name="dont_round_avatar">ユーザ画像を角丸にしない(アプリ再起動が必要)</string>
|
||||
<string name="color_and_background">色と背景</string>
|
||||
<string name="column_background">カラム背景</string>
|
||||
<string name="column_header">カラムヘッダ</string>
|
||||
<string name="foreground_color">文字とアイコンの色</string>
|
||||
<string name="image">画像</string>
|
||||
<string name="image_alpha">画像の不透明度</string>
|
||||
<string name="menu">メニュー</string>
|
||||
<string name="open_in_pseudo_account">疑似アカウント %1$s で開く</string>
|
||||
<string name="pick_image">画像の選択</string>
|
||||
</resources>
|
||||
|
|
|
@ -70,6 +70,8 @@
|
|||
<!-- 投稿画面のEditTextの下に引くFrameLayoutの背景 -->
|
||||
<attr name="colorPostFormBackground" format="color"/>
|
||||
|
||||
<!-- カラムストリップの背景色 -->
|
||||
<attr name="colorColumnStripBackground" format="color"/>
|
||||
|
||||
<attr name="btn_attachment" format="reference" />
|
||||
<attr name="btn_boost" format="reference" />
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<color name="Light_colorColumnListItemText">#80000000</color>
|
||||
<color name="Light_colorTimeSmall">#80000000</color>
|
||||
<color name="Light_colorAcctSmall">#80000000</color>
|
||||
<color name="Light_colorColumnHeaderAcct">#80000000</color>
|
||||
<color name="Light_colorColumnHeaderPageNumber">#80000000</color>
|
||||
<color name="Light_colorSettingDivider">#80000000</color>
|
||||
|
||||
<color name="Light_colorImageButton">#99343434</color>
|
||||
|
||||
<color name="Light_colorAccent">#5a5a5a</color>
|
||||
|
||||
<color name="Light_colorRippleEffect">#FF808080</color>
|
||||
<color name="Light_colorColumnListItemText">#808080</color>
|
||||
<color name="Light_colorTimeSmall">#808080</color>
|
||||
<color name="Light_colorAcctSmall">#808080</color>
|
||||
<color name="Light_colorColumnHeaderAcct">#808080</color>
|
||||
<color name="Light_colorColumnHeaderPageNumber">#808080</color>
|
||||
|
||||
<color name="Light_colorSettingDivider">#808080</color>
|
||||
|
||||
<color name="Light_colorColumnListDragHandleBackground">#80cccccc</color>
|
||||
<color name="Light_list_item_bg_pressed_dragged">#AACCCCCC</color>
|
||||
|
@ -27,8 +28,11 @@
|
|||
|
||||
<color name="Light_colorPostFormBackground">#eee</color>
|
||||
|
||||
<color name="Light_colorColumnStripBackground">#FFFFFFFF</color>
|
||||
|
||||
<color name="Light_colorProfileBackgroundMask">#C0FFFFFF</color>
|
||||
|
||||
|
||||
<color name="Light_colorPrimaryDark">#303030</color>
|
||||
|
||||
<!-- 以下は白テーマでも黒テーマでもだいたい同じ -->
|
||||
|
@ -44,18 +48,20 @@
|
|||
|
||||
<!-- Dark theme -->
|
||||
|
||||
<color name="Dark_colorColumnListItemText">#66FFFFFF</color>
|
||||
<color name="Dark_colorTimeSmall">#66FFFFFF</color>
|
||||
<color name="Dark_colorAcctSmall">#66FFFFFF</color>
|
||||
<color name="Dark_colorColumnHeaderAcct">#66FFFFFF</color>
|
||||
<color name="Dark_colorColumnHeaderPageNumber">#66FFFFFF</color>
|
||||
<color name="Dark_colorSettingDivider">#66FFFFFF</color><!-- ダイアログ背景が#424242なので、それより明るくないといけない -->
|
||||
|
||||
|
||||
<color name="Dark_colorImageButton">#ccFFFFFF</color>
|
||||
|
||||
<color name="Dark_colorAccent">#ccFFFFFF</color>
|
||||
|
||||
<color name="Dark_colorRippleEffect">#FF666666</color>
|
||||
<color name="Dark_colorColumnListItemText">#666</color>
|
||||
<color name="Dark_colorTimeSmall">#666</color>
|
||||
<color name="Dark_colorAcctSmall">#666</color>
|
||||
<color name="Dark_colorColumnHeaderAcct">#666</color>
|
||||
<color name="Dark_colorColumnHeaderPageNumber">#666</color>
|
||||
|
||||
<color name="Dark_colorSettingDivider">#666</color><!-- ダイアログ背景が#424242なので、それより明るくないといけない -->
|
||||
|
||||
<color name="Dark_colorColumnListDragHandleBackground">#80444444</color>
|
||||
<color name="Dark_list_item_bg_pressed_dragged">#AA444444</color>
|
||||
|
@ -72,6 +78,8 @@
|
|||
<color name="Dark_colorProfileBackgroundMask">#C0000000</color>
|
||||
<color name="Dark_colorBackground">#000</color>
|
||||
|
||||
<color name="Dark_colorColumnStripBackground">#000</color>
|
||||
|
||||
<color name="Dark_colorPrimaryDark">#222</color>
|
||||
|
||||
<!-- 以下は白テーマでも黒テーマでもだいたい同じ -->
|
||||
|
|
|
@ -272,4 +272,14 @@
|
|||
<string name="clear_text">Cleat text</string>
|
||||
<string name="clear_text_and_media">Clear text and media</string>
|
||||
<string name="dont_round_avatar">Don\'t round corner of avatar image (app restart required)</string>
|
||||
<string name="menu">Menu</string>
|
||||
<string name="open_in_pseudo_account">open in pseudo account %1$s</string>
|
||||
|
||||
<string name="color_and_background">Color and Background…</string>
|
||||
<string name="column_background">column background</string>
|
||||
<string name="pick_image">pick image</string>
|
||||
<string name="image_alpha">image alpha</string>
|
||||
<string name="image">image</string>
|
||||
<string name="column_header">column header</string>
|
||||
<string name="foreground_color">foreground color</string>
|
||||
</resources>
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
<item name="colorRegexFilterError">@color/Light_colorRegexFilterError</item>
|
||||
<item name="colorPostFormBackground">@color/Light_colorPostFormBackground</item>
|
||||
<item name="colorColumnStripBackground">@color/Light_colorColumnStripBackground</item>
|
||||
|
||||
|
||||
<item name="btn_attachment">@drawable/btn_attachment</item>
|
||||
|
@ -123,6 +124,7 @@
|
|||
<item name="colorSettingDivider">@color/Dark_colorSettingDivider</item>
|
||||
<item name="colorRegexFilterError">@color/Dark_colorRegexFilterError</item>
|
||||
<item name="colorPostFormBackground">@color/Dark_colorPostFormBackground</item>
|
||||
<item name="colorColumnStripBackground">@color/Dark_colorColumnStripBackground</item>
|
||||
|
||||
<item name="btn_attachment">@drawable/btn_attachment_dark</item>
|
||||
<item name="btn_boost">@drawable/btn_boost_dark</item>
|
||||
|
|
Loading…
Reference in New Issue